About QR Code Generator
Most "QR code generator" tools online are, underneath, a thin form that submits your text to a third-party server, which does the actual encoding and hands back an image — meaning whatever you're encoding (a Wi-Fi password, a personal phone number, an address) passes through and is potentially logged by a server you have no visibility into. This tool is a genuine from-scratch implementation of the QR code standard (ISO/IEC 18004) running entirely as JavaScript in your browser: every step, from turning your text into raw data bits through to the finished grid of black-and-white squares, happens on your device, and nothing is ever transmitted anywhere.
Building a real QR encoder from first principles is a substantial undertaking, so this tool deliberately and transparently scopes down which parts of the full standard it implements, favouring a smaller set of genuinely correct, genuinely scannable QR codes over an ambitious attempt at the full 40-version, four-mode specification that risks subtle, hard-to-notice bugs. Three scope decisions matter most. First, **only byte mode** is implemented — the encoding mode suited to arbitrary UTF-8 text, which is what URLs, Wi-Fi strings, email addresses and plain messages all are; the standard's separate, more compact Numeric and Alphanumeric modes (which pack digits-only or a restricted character set more tightly) aren't implemented, which very slightly reduces the maximum length available for input made up purely of digits or uppercase letters compared to what a fully-featured encoder could manage, but never affects whether a given input can be encoded at all in byte mode. Second, **QR versions 1 through 5 only** (versions are the standard's name for the different available grid sizes, from a compact 21×21 up through much larger grids for longer content) — and third, restricted further to only the specific (version, error-correction level) combinations that use a **single Reed-Solomon error-correction block**, since the standard's block-splitting and interleaving rules for larger, multi-block codes add substantial extra complexity that would meaningfully increase the risk of a subtle, hard-to-catch encoding bug. Both restrictions are deliberately conservative rather than a workaround for something being broken — everything within this narrower scope is implemented and verified as a complete, correct, standard-compliant instance of the specification.
In concrete terms, this caps the maximum input length depending on which error correction level you choose: 106 bytes at level L, 42 bytes at level M, 20 bytes at level Q, or 14 bytes at level H — comfortably enough for a URL, a Wi-Fi network name and password together, an email address, a phone number, or a short message, which covers the overwhelming majority of real-world QR code use, but not enough for a long paragraph of text at higher error-correction levels. If your input is too long for the level you've picked, the tool tells you the exact limit and suggests trying a lower error-correction level rather than silently producing a corrupted or unscannable result.
Error correction level itself controls how much of the code's data can be physically damaged, dirty, or obscured (by a logo overlay, a crease, a scuff) and still scan correctly, at the direct cost of how much of the code's total capacity goes toward that redundancy rather than your actual content — L recovers roughly 7% damage and leaves the most room for data, right up through H, which recovers roughly 30% damage but leaves noticeably less room, which is exactly why the maximum input length shrinks so much as the level rises. One more simplification, and a genuinely inconsequential one: the standard defines 8 different "mask patterns" — different fixed geometric patterns XORed over the raw data to avoid accidentally creating large solid blocks or patterns that confuse a scanner — and a fully optimised encoder tries all 8 and picks whichever produces the fewest problematic-looking patterns by a scoring formula. This tool always applies a single fixed mask (mask pattern 0) instead of running that comparison. This does not make the resulting code any less correctly scannable — the code's format information correctly declares which mask was used, exactly as a fully optimised encoder's chosen mask would be declared, so any real-world scanner reads it exactly the same way — it simply means the visual pattern isn't quite as evenly distributed as it could theoretically be, an entirely cosmetic difference with no effect on reliability.