QR Code Generator

A real QR code as SVG: any text, URL or wifi string, four error correction levels, and no request to anyone else's server.

Enable JavaScript to encode your own text; the code below is for the default.

Nothing is uploaded. The code is built in this tab, which is not true of most QR generators.

Error correction

How much of the code can be damaged and still read: L about 7 percent, M 15, Q 25, H 30. Higher means a denser code for the same text.

The width attribute on the SVG. It scales cleanly whatever this is, so it only matters for a fixed-size export.

The margin. Four is the standard minimum; below that some readers give up.

Auto picks the mask with the lowest penalty, which is what the standard asks for. Forcing one is for comparing output with another encoder.

Hex only. Keep the contrast high: readers threshold the image, and a pale code on white stops scanning.

Output

The data URI is percent encoded rather than base64, so it is smaller and readable, and works in a CSS background.

Version 3, level M, byte mode, mask 3. 29×29 modules, 31 of about 42 used at this version.

Scan it with a phone before you print anything. It is a two second check and the only one that matters.

qr-code.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 37" width="296" height="296" shape-rendering="crispEdges" role="img" aria-label="QR code, version 3, level M">
	<rect width="37" height="37" fill="#FFFFFF"/>
	<path fill="#000000" d="M4 4h7v1h-7zM12 4h5v1h-5zM19 4h2v1h-2zM23 4h2v1h-2zM26 4h7v1h-7zM4 5h1v1h-1zM10 5h1v1h-1zM12 5h2v1h-2zM18 5h2v1h-2zM24 5h1v1h-1zM26 5h1v1h-1zM32 5h1v1h-1zM4 6h1v1h-1zM6 6h3v1h-3zM10 6h1v1h-1zM13 6h2v1h-2zM16 6h4v1h-4zM23 6h1v1h-1zM26 6h1v1h-1zM28 6h3v1h-3zM32 6h1v1h-1zM4 7h1v1h-1zM6 7h3v1h-3zM10 7h1v1h-1zM12 7h1v1h-1zM14 7h1v1h-1zM16 7h1v1h-1zM20 7h2v1h-2zM24 7h1v1h-1zM26 7h1v1h-1zM28 7h3v1h-3zM32 7h1v1h-1zM4 8h1v1h-1zM6 8h3v1h-3zM10 8h1v1h-1zM14 8h1v1h-1zM16 8h2v1h-2zM23 8h1v1h-1zM26 8h1v1h-1zM28 8h3v1h-3zM32 8h1v1h-1zM4 9h1v1h-1zM10 9h1v1h-1zM18 9h1v1h-1zM21 9h3v1h-3zM26 9h1v1h-1zM32 9h1v1h-1zM4 10h7v1h-7zM12 10h1v1h-1zM14 10h1v1h-1zM16 10h1v1h-1zM18 10h1v1h-1zM20 10h1v1h-1zM22 10h1v1h-1zM24 10h1v1h-1zM26 10h7v1h-7zM12 11h7v1h-7zM21 11h3v1h-3zM4 12h1v1h-1zM6 12h2v1h-2zM9 12h3v1h-3zM14 12h1v1h-1zM17 12h2v1h-2zM20 12h2v1h-2zM26 12h1v1h-1zM29 12h1v1h-1zM31 12h2v1h-2zM4 13h1v1h-1zM6 13h2v1h-2zM9 13h1v1h-1zM12 13h1v1h-1zM16 13h1v1h-1zM19 13h5v1h-5zM26 13h3v1h-3zM32 13h1v1h-1zM5 14h2v1h-2zM8 14h3v1h-3zM12 14h2v1h-2zM16 14h1v1h-1zM18 14h2v1h-2zM22 14h1v1h-1zM25 14h1v1h-1zM27 14h2v1h-2zM30 14h2v1h-2zM4 15h1v1h-1zM6 15h4v1h-4zM12 15h1v1h-1zM16 15h4v1h-4zM22 15h1v1h-1zM26 15h2v1h-2zM32 15h1v1h-1zM4 16h1v1h-1zM6 16h1v1h-1zM8 16h1v1h-1zM10 16h1v1h-1zM13 16h2v1h-2zM16 16h1v1h-1zM20 16h2v1h-2zM24 16h1v1h-1zM29 16h2v1h-2zM4 17h2v1h-2zM8 17h1v1h-1zM17 17h1v1h-1zM21 17h3v1h-3zM25 17h2v1h-2zM30 17h3v1h-3zM10 18h1v1h-1zM13 18h2v1h-2zM18 18h1v1h-1zM22 18h2v1h-2zM26 18h2v1h-2zM30 18h3v1h-3zM4 19h4v1h-4zM11 19h1v1h-1zM14 19h1v1h-1zM17 19h1v1h-1zM19 19h1v1h-1zM22 19h4v1h-4zM31 19h1v1h-1zM4 20h1v1h-1zM6 20h1v1h-1zM9 20h4v1h-4zM15 20h1v1h-1zM22 20h4v1h-4zM27 20h3v1h-3zM31 20h1v1h-1zM7 21h3v1h-3zM13 21h1v1h-1zM16 21h2v1h-2zM21 21h1v1h-1zM24 21h1v1h-1zM27 21h1v1h-1zM29 21h3v1h-3zM4 22h1v1h-1zM8 22h3v1h-3zM13 22h1v1h-1zM16 22h1v1h-1zM21 22h1v1h-1zM24 22h1v1h-1zM26 22h2v1h-2zM30 22h1v1h-1zM6 23h2v1h-2zM11 23h2v1h-2zM15 23h2v1h-2zM19 23h4v1h-4zM24 23h1v1h-1zM30 23h1v1h-1zM5 24h2v1h-2zM8 24h1v1h-1zM10 24h1v1h-1zM14 24h1v1h-1zM16 24h2v1h-2zM19 24h4v1h-4zM24 24h7v1h-7zM12 25h2v1h-2zM16 25h4v1h-4zM21 25h2v1h-2zM24 25h1v1h-1zM28 25h5v1h-5zM4 26h7v1h-7zM12 26h4v1h-4zM17 26h1v1h-1zM20 26h1v1h-1zM22 26h3v1h-3zM26 26h1v1h-1zM28 26h2v1h-2zM31 26h1v1h-1zM4 27h1v1h-1zM10 27h1v1h-1zM12 27h1v1h-1zM14 27h1v1h-1zM19 27h1v1h-1zM22 27h1v1h-1zM24 27h1v1h-1zM28 27h2v1h-2zM31 27h1v1h-1zM4 28h1v1h-1zM6 28h3v1h-3zM10 28h1v1h-1zM14 28h3v1h-3zM18 28h1v1h-1zM21 28h1v1h-1zM24 28h5v1h-5zM30 28h1v1h-1zM32 28h1v1h-1zM4 29h1v1h-1zM6 29h3v1h-3zM10 29h1v1h-1zM12 29h1v1h-1zM15 29h2v1h-2zM18 29h2v1h-2zM23 29h1v1h-1zM25 29h1v1h-1zM28 29h2v1h-2zM31 29h1v1h-1zM4 30h1v1h-1zM6 30h3v1h-3zM10 30h1v1h-1zM12 30h1v1h-1zM17 30h2v1h-2zM22 30h1v1h-1zM25 30h1v1h-1zM27 30h1v1h-1zM30 30h1v1h-1zM32 30h1v1h-1zM4 31h1v1h-1zM10 31h1v1h-1zM13 31h5v1h-5zM22 31h1v1h-1zM24 31h1v1h-1zM27 31h1v1h-1zM29 31h1v1h-1zM31 31h1v1h-1zM4 32h7v1h-7zM12 32h2v1h-2zM16 32h1v1h-1zM18 32h1v1h-1zM20 32h1v1h-1zM22 32h4v1h-4zM27 32h1v1h-1zM29 32h1v1h-1zM31 32h1v1h-1z"/>
</svg>

Most QR generators post your text to their server, which is an odd thing to do with a wifi password. This one encodes in the page: the Reed-Solomon arithmetic, the mask selection and the SVG all happen in the tab you have open, and nothing leaves it.

The output is SVG, so the code is sharp at any size, including printed.

How to use

  1. Put in the text. A URL, a phone number, a wifi string, anything up to 300 characters.
  2. Pick the error correction. M is the usual choice. H survives more damage and dirt, at the cost of a denser code for the same text.
  3. Leave the quiet zone at 4 unless you know the reader. It is the standard minimum, and below it some readers stop finding the code at all.
  4. Copy the SVG, or switch to the data URI for a CSS background.

Scan the preview with a phone before you print anything. That is a two second check and the only one that matters.

Example

A wifi network, which is the case worth knowing the format for:

WIFI:T:WPA;S:Bucket Guest;P:hunter2hunter2;;

T is the security type (WPA, WEP, or nopass), S the network name and P the password. The two semicolons at the end are not a typo: the format needs the empty field and the terminator. Phones join the network from it without anyone reading the password out loud.

Those 44 bytes at level M come out as a version 4 code, 33 by 33 modules. The same string at level L fits in version 3, 29 by 29, and at level H it needs version 5, 37 by 37, because the stronger correction takes the space the text was using. The line under the preview says which version you landed on and how much room is left in it.

Other formats worth knowing:

tel:+441234567890
mailto:[email protected]?subject=Hello
BEGIN:VCARD
VERSION:3.0
FN:Liton Arefin
EMAIL:[email protected]
END:VCARD

Pitfalls

Colour inversion breaks scanning. A light module on a dark background is not a QR code to most readers: they expect dark on light. If you need a dark theme, put the code on a light panel rather than inverting it.

Low contrast breaks scanning too. Readers threshold the image to black and white before they do anything else. A grey code on a white card may look elegant and read as nothing.

A logo in the middle is not free. It works because the error correction absorbs it, so a code with a logo needs level H and a logo no wider than about a fifth of the code. This tool does not add one, deliberately: the ones that do often produce codes that scan in the preview and not on paper.

The quiet zone is part of the code. Cropping it off, or putting the code flush against other artwork, is the most common reason a printed code fails.

300 characters is the limit here. This encoder goes up to version 10, which holds about 271 bytes at level L. A longer payload needs versions 11 to 40, and usually needs a shortened URL instead.

Compatibility

The codes follow ISO/IEC 18004, versions 1 to 10, with numeric, alphanumeric and byte mode, the four error correction levels, and the mask chosen by the four penalty rules from the standard. Text is UTF-8 in byte mode, which is what every phone camera assumes.

The output was checked against a decoder rather than by eye: 127 codes covering every version, every level, every mask and all three modes were drawn to a canvas and read back with the browser’s BarcodeDetector, which on macOS is Apple’s own scanner. All 127 decoded to exactly the input string.

The SVG uses one <path> of merged runs and shape-rendering="crispEdges", so it stays sharp at any scale and is a fraction of the size of a rect-per-module SVG. It works in every browser that renders SVG at all, and in Illustrator, Figma and Inkscape.

Frequently asked questions

Can I get a PNG?
Not directly. Open the SVG in a browser and screenshot it, or use any vector tool to export at the size you need. A PNG from a vector source at the exact print size beats a scaled-up one.
Which error correction level should I use?
M for anything on a screen. Q or H for anything printed, put outdoors, or likely to get scuffed, because that is what the correction is for. L only when the text is long and the code has to stay small.
Why did my code get bigger when I changed a letter?
Mode. A string of only digits uses numeric mode, about 3.3 bits a character. Upper case letters and a few symbols use alphanumeric mode, 5.5 bits. Anything else is byte mode, 8 bits or more. One lower case letter in a URL moves the whole string to byte mode, which can push it up a version.
Does HTTPS://EXAMPLE.COM really make a smaller code?
Yes, and it still works: the scheme and host are case-insensitive. Upper case keeps the string in alphanumeric mode. The path is case-sensitive, so only do it for a bare domain.
Is the mask choice the same as other generators?
It should be. The four penalty rules are in the standard and this implements all four, so a given text and level lands on the same mask any conforming encoder picks. You can also force a mask, which is useful for comparing output.
Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.