QR Code Generator
Type a link, some text, a Wi-Fi network or an email, and this page encodes a standards-compliant QR symbol in your browser, shows you the version it chose, and exports it as a PNG or a crisp SVG.
Everything below is generated locally in this tab. The form works without JavaScript, but the QR image itself is produced by the script on this page, so enable JavaScript to see and download a symbol.
Higher levels add error-correction codewords, which makes the symbol larger for the same payload but far more tolerant of scratches, glare and smudges.
No code generated yet.
Self-check: not run yet.
Output
The QR image appears here once JavaScript has drawn it.
This is exactly what a reader will receive. For a Wi-Fi payload it includes the password in clear text, so treat the preview like the code itself.
How it works
A QR code is not an image format, it is a specification for arranging binary data on a square grid. This page implements that specification directly: the same steps a commercial encoder performs, in plain JavaScript, with no library in the middle. Encoding starts by serialising your payload to UTF-8 bytes, writing the four-bit mode indicator for byte mode and a character-count indicator whose width depends on the version. Then it picks the version. Versions 1 to 40 define matrices of 21×21 up to 177×177 modules, and each version and error-correction level has a fixed capacity, so the encoder walks the capacity table and takes the first version that fits.
The data codewords are split into blocks, and each block gains Reed–Solomon parity codewords computed over GF(256) with the primitive polynomial 0x11d and the standard generator polynomials. The blocks are then interleaved — data codewords first, then parity — so that a scratch or a smear damages a little of every block instead of destroying one whole block. The resulting bit stream is poured into the matrix in the two-module-wide zigzag defined by the standard, skipping the function patterns that were drawn first: the three finder patterns and their separators, the timing patterns, the alignment patterns and the single dark module. Because the character-count indicator and capacity depend on the version, and the version partly depends on the payload length, the smallest-fit search is done before any bits are written.
A finished matrix is rarely readable as-is, so a mask is applied. The standard defines eight mask patterns, and the encoder builds all eight candidate matrices and scores each one with four penalty rules: runs of five or more same-coloured modules in a row or column, 2×2 blocks of one colour, finder-like patterns that could confuse a locator, and an imbalance between dark and light modules across the whole symbol. The mask with the lowest total penalty wins. Finally the encoder writes the format information — the error-correction level and mask number, protected by a BCH(15,5) code and XORed with the fixed mask 0x5412 — and for version 7 and above the 18-bit version information, also BCH-protected. Both of those are redundant copies placed in two locations, which is what lets a reader lock on to a symbol that is partly damaged.
Accuracy, limits and honest caveats
The encoder is complete for byte mode across the whole standard, and it is deliberately strict about what it will not do. Byte mode encodes UTF-8 text as a sequence of bytes; the numeric and alphanumeric modes that the standard defines for digits and uppercase ASCII are not implemented, so a payload made only of digits takes more room here than a dedicated encoder would use. That is a size difference, never a correctness one — a reader sees a perfectly ordinary byte-mode symbol either way.
- Version 40 is the ceiling. Version 40 is 177×177 modules and holds 2,953 bytes at level L, 2,331 at M, 1,663 at Q and 1,273 at H. If your payload still does not fit, the page says so and produces nothing rather than emitting a truncated or malformed symbol. In practice this is not a wall you hit often: a very long URL or a whole paragraph of text gets there first, and the honest answer at that point is to shorten the content or split it across codes.
- Error correction is not magic. The percentages are roughly 7, 15, 25 and 30 per cent, and they describe how much of the symbol can be damaged or misread, not how small the symbol can be printed. Choosing H to make a code "safer" also increases the module count for the same payload, which can make the printed result harder to resolve. For a clean screen or a clean label, M is usually the sensible middle.
- Colour and contrast decide whether it scans. Most decoders assume dark modules on a light background, and a colour-inverted code may be rejected outright by older or stricter readers even when a modern phone camera handles it. Low contrast is worse: a pale grey on white, a mid-tone accent on a slightly lighter tint, or a dark red on black all fail the brightness difference the image-processing step relies on. Dark on light, comfortably far apart in luminance, is the rule.
- The quiet zone matters more than people expect. The standard asks for at least four light modules of margin on every side; the default here is four, and you can add more. Shrinking it to zero, or placing the symbol flush against a dark border or another graphic, removes the separation a locator needs and is one of the most common causes of a code that "should work" but does not.
- The preview is a preview. The canvas is scaled to the pixel size you asked for and the SVG is exact, but a very small output size on a high-density screen, or a browser zoom level, can make the on-screen version look softer than the exported file. Judge print quality from the downloaded PNG or SVG, not from the preview.
- This is an encoder, not a scanner. The page builds symbols and verifies its own reserved areas; it does not decode with a camera. Before you print a run of labels, scan the exported file with the reader you expect your audience to use.
Wi-Fi payloads contain the network password in plain text, and a QR code is simply a picture of that string. Anyone who can photograph the code can read the password. Treat a Wi-Fi code the way you would treat a written-down password, and use the guest network for anything you are going to print or post.
How to use this tool
- Choose what the code holds. Pick plain text or a link, a Wi-Fi network, an email, a phone number or an SMS. The form swaps in the fields that payload needs — for Wi-Fi that is the network name, the password and the security type, and for email it is a recipient, a subject and a body.
- Pick the error-correction level. Levels L, M, Q and H trade capacity for resilience. M is the usual default for screens and clean print; use Q or H when the code will be exposed to wear or partial damage, and expect a larger symbol or a higher version in exchange.
- Set the size, margin and colours. The pixel size drives the PNG; the SVG is resolution-independent, so a modest size is fine for print. Leave the margin at four modules unless you have a reason to change it, and keep a light background with dark modules.
- Generate, then read the readouts. The status line reports the version chosen, the matrix size and the mask number, and the payload preview shows the exact string a scanner will receive. If the payload is too long for version 40 at that level, the message says so — lower the level or shorten the content.
- Check the self-check line before you download. The script re-reads the format information out of its own finished matrix, removes the fixed mask and confirms the decoded error-correction level and mask match the intent. A "self-check passed" line means the reserved areas are internally consistent.
- Export the format that suits the job. PNG is a fixed-size raster, ideal for a screen, a slide or a chat message. SVG is vector, so it stays sharp at any print size and is the better choice for labels, posters and anything that may be enlarged later.
The tests get shorter as the payload gets shorter, but the principle is the same: a plain URL such as
https://example.com is only 19 bytes, so at level M the encoder fits it into a small
version and produces a chunky, easy-to-scan symbol, while the same text at level H pushes the version
up and the modules get finer. If a code is hard to scan in the wild, the fix is almost always to
shorten the payload, raise the contrast or increase the printed size — not to change the mask.
Frequently asked questions
Which QR versions and error-correction levels does this page support?
Versions 1 to 40, the complete range defined by ISO/IEC 18004, at all four error-correction levels L, M, Q and H. The page always chooses the smallest version whose data capacity fits your payload at the level you picked, so a short link usually lands on version 2 or 3 while a long Wi-Fi string may need version 10 or more. Anything that will not fit in version 40 at the selected level is reported as too long instead of being encoded into an invalid symbol.
Does the payload leave my device, and can the page work offline?
No and yes. The encoder, the Reed–Solomon arithmetic, the mask scoring and the rendering all run as plain JavaScript in this tab, with no network requests, no external scripts, no fonts and no QR library. You can load the page once, switch off Wi-Fi and keep generating codes. The trade-off is that nothing is stored: close or reload the tab and your payload is gone, so keep the downloaded file or the original text if you need it later.
Why does a code sometimes fail to scan even though it looks fine on screen?
Most reader failures are optical rather than mathematical. Inverted colours, a foreground and background that are too close in brightness, a quiet zone that is too narrow, a very small print size, a glossy screen, or a camera that is too close and cannot focus all cause a miss. A code with a large module count is also harder to read from a distance than a short one. High error-correction levels tolerate more damage and smudging, but they cannot compensate for a symbol that is simply too small or too low in contrast.
What does the self-check indicator actually verify?
After building a matrix, the script reads the 15 format-information modules back out of the finished grid, removes the fixed mask and decodes them, then compares the recovered error-correction level and mask number with the ones it intended to write. If those agree it reports that the self-check passed; if they do not, it says so loudly rather than shipping a silently broken image. That check is a sanity test on the reserved format area, not a full independent scanner, so a standard reader is still the final word.
Sources & further reading
- ISO/IEC 18004 — QR Code bar code symbology specification — The normative standard this encoder follows: byte-mode encoding, the version 1–40 capacity and block tables, Reed–Solomon error correction, mask evaluation and the format and version information layout.
- MDN Web Docs — Canvas API — Documents the canvas element, 2D context drawing calls and toBlob() used to rasterise the module matrix into the downloadable PNG.
- MDN Web Docs — SVG: Scalable Vector Graphics — Reference for the SVG elements, namespace and viewBox scaling used to build the vector version of the symbol that stays crisp when printed.