Phone QR Code Generator
One scan brings up your number in the dialer — the visitor just confirms the call. The simplest of all QR codes, and the one that most often gets the number format wrong; this generator fixes that for you.
Print checklist
- Keep the white margin around the code — it is the quiet zone scanners need, not empty space to crop.
- Size for the scan distance: at least 2 × 2 cm for arm's-length scanning, and roughly one tenth of the farthest scan distance for posters.
- Scan a test print with a real phone before making copies.
The tel: format, done properly
The code carries a tel: link — the URI scheme defined in RFC 3966 — and inside
it your number in E.164 global form: a +, the country code, then the subscriber
digits, with nothing else. The engine follows the ZXing Barcode Contents guidance it cites,
which is to encode the most complete version of the number possible; those spec sources were
last verified against the live documents on 2026-07-20. The payload holds no name, no label
and no display formatting. Everything a phone needs in order to offer the call is the scheme
and the digits.
The generator accepts human formatting and normalizes it. Spaces, dots, dashes and parentheses
are stripped as separators; a leading 00 is accepted as an alias for
+; what remains must be + followed by a run of digits. So
+1 (555) 013-2000 and 001 555 013 2000 produce the same payload — the
build that produced this page checks that they do, and would fail if they ever diverged. Because
the normalized number contains only + and digits, a tel:
payload needs no percent-encoding, unlike the mailto: and sms:
payloads on this site, where user-typed text is percent-encoded. That is why the payload is so short,
and why the symbol below is so small.
Scanning never dials by itself: every phone shows the number and asks for confirmation. A phone code cannot rack up premium-rate calls behind anyone's back — worth knowing both as a printer of codes and as a scanner of them.
Guide: tel: is one of several URI-scheme payloads this site builds. URI schemes: mailto, tel, sms and WhatsApp sets them side by side — what each payload contains, where percent-encoding applies, and the wa.me
number rule — with every example built by the engine. More in the
guides index.
Worked example
The formatted input +1 (555) 013-2000 is normalized into:
tel:+15550132000
Short payload, tiny code — version 2 with only 25×25 modules. Phone codes print small and scan effortlessly; they are the most forgiving type.
More inputs, one normalization
Each row below was produced at build time by buildPhonePayload, the function the
generator above calls, from an obviously fictional number; the symbol facts come from the same
encoder that drew the worked example. If the engine's normalization ever changed, these rows
would change with it or the build would fail — the guarantee the
methodology page makes for every worked example on the site.
| Typed input | What it shows | Payload | Symbol |
|---|---|---|---|
001 555 013 2000 | the 00 international prefix instead of + | tel:+15550132000 | version 2, 25×25 modules, EC Q |
+1.555.013.2000 | dots as separators | tel:+15550132000 | version 2, 25×25 modules, EC Q |
+44 20 7946 0958 | another country code, spaces only | tel:+442079460958 | version 2, 25×25 modules, EC Q |
The first two rows are the worked example's number in two other notations, and they land on
the identical payload: the separators are formatting, not data, and the 00
prefix is rewritten to +. The third row carries a different country code and a
different digit count; its payload is 17 characters long against
16 for the worked example, and the encoder chose version
2 for it. The version is chosen by the encoder from the payload and the error-correction
level, and the symbol's side in modules is defined by the engine as 17 + 4 × version
— so a version 2 symbol is
25 modules across, which the build also checks.
What the generator refuses — in its own words
When an input cannot be normalized to E.164 the builder returns an error instead of a payload, and the generator shows that error beside the field. The messages below are the engine's own, captured at build time; the build fails if the engine ever starts accepting one of these inputs.
-
555 013 2000— “Include the country code in international format, e.g. +1 555 123 4567.” -
+1 555 CALL NOW— “Use only digits, spaces, dashes, and parentheses.” -
+0 20 7946 0958— “An international number has 7–15 digits and cannot start with 0 after the country code prefix.” -
+1234 5678 9012 3456— “An international number has 7–15 digits and cannot start with 0 after the country code prefix.”
Note what is not on that list. A number that is syntactically perfect but belongs to nobody passes every check, because every check is a check on the shape of the digits. The next section is about that gap.
Reading the symbol facts
A QR code has two independent layers. The payload is the text above; the symbol is the matrix of modules that carries it, produced to ISO/IEC 18004 by a vendored copy of the reference encoder (Project Nayuki's qrcodegen), kept byte-comparable with upstream. Most "my code doesn't work" problems are payload problems, which is why this page spends its space on the payload — but the symbol facts under each example are worth reading too.
The worked example was requested at error-correction level M, the engine's default when no logo is present. The level in the symbol facts is the level actually encoded, and it can be higher than the one requested: the reference encoder raises the level when doing so does not increase the version. Requesting each of the four levels for the worked example's payload gives:
| Requested | Encoded | Version | Modules |
|---|---|---|---|
| L | L | 1 | 21×21 |
| M | Q | 2 | 25×25 |
| Q | Q | 2 | 25×25 |
| H | H | 3 | 29×29 |
Where two rows share a version, the encoder boosted the lower request to the higher level at no cost; where the version rises, the extra correction was paid for with a larger symbol. Either way the payload is unchanged — error correction is a property of the symbol layer only.
Around the symbol sits the quiet zone: 4 blank modules on every side, required by the standard, rendered into every download and impossible to switch off. The worked example is therefore drawn 33 modules across, of which the outer 4 on each side carry no data — and the PNG and SVG you download include them.
The PNG download offers presets of 512, 1024, 2048 pixels. The readout the generator
shows beside each preset is computed by printSizeAt300Dpi at
300 DPI, and the quiet zone is inside those pixels, so the figure is the printed
footprint including the blank border. For the worked example's 33 modules:
- 512 px: 1.71 in × 1.71 in (43.3 mm × 43.3 mm) at 300 DPI — about 1.31 mm per module.
- 1024 px: 3.41 in × 3.41 in (86.7 mm × 86.7 mm) at 300 DPI — about 2.63 mm per module.
- 2048 px: 6.83 in × 6.83 in (173.4 mm × 173.4 mm) at 300 DPI — about 5.25 mm per module.
Error correction helps a damaged code scan, but print size and contrast still matter. The quiet zone and print size guide takes the presets further, and how a QR code encodes data explains the version and level columns from first principles.
What this generator cannot verify
The engine validates format, not truth. It cannot know whether a phone number is reachable, whether it is yours, or whether it will still be in service when the sticker is a year old. Every check in the rejection list above is a check on the shape of the digits, and a number with two digits transposed has exactly the same shape as the right one.
The clearest illustration is a notation many people type without thinking. Parentheses are
stripped as separators, but a digit inside them is a digit and is kept:
+44 (0)20 7946 0958 normalizes to tel:+4402079460958. Whether that
zero belongs in the international form is exactly the kind of truth the generator cannot check
— it has no table of national dialling conventions, only the E.164 shape. Read the normalized
payload the generator shows you, digit by digit, before anything is printed.
What is encoded is also permanent. Every code here is static: the number lives in the image itself, with no redirect through our servers. That is why the code never expires and cannot be held hostage — and why it cannot be edited after printing and its scans cannot be counted. A changed number means a new code and a new print run; the trade-off is laid out in static vs dynamic QR codes.
Treat a freshly generated code as untested until a real device has scanned it and the dialer has shown the number you expected.
Common misreadings
- Cropping the quiet zone. The white border in the download is part of the symbol. The 4-module quiet zone is rendered into every PNG and SVG and cannot be disabled; trimming it away in an image editor, or printing the code flush against artwork, is the most common self-inflicted scan failure.
- Inverting the colours. The style panel evaluates every colour pair with the WCAG relative-luminance contrast formula. Black on white measures 21:1 and raises no warning. Swap the two and the ratio is unchanged, but the panel warns: “Light-on-dark (inverted) codes are not reliably read by all scanners. Prefer dark modules on a light background.” Light-on-dark codes are rejected by many scanners, so the warning stands even at full contrast.
- Grey modules. The warning threshold is 4.5:1. A
mid-grey such as
#8a8a8aon white computes to 3.45:1 and triggers: “Low contrast (3.45:1). Scanners may fail below 4.5:1 — darken the foreground or lighten the background.” More pairs are worked through in contrast and inverted codes. - A wrong digit encodes fine. Transpose two digits, or keep a bracketed zero that should not be there, and the result is still a well-formed E.164 number. The engine encodes it without complaint and the symbol scans cleanly — to the wrong number. Only a test call catches it.
- Adding a logo and expecting the same symbol. A logo overlay forces error correction H and is capped at 16% of the symbol area — a cap that is decode-tested in the round-trip suite rather than derived from the theoretical EC-H ceiling. With a logo present, the level table above collapses to its H row.
Where scan-to-call earns its place
- Service stickers: on the boiler, the lift panel, the vending machine — "Fault? Scan to call" removes every barrier between the problem and the report.
- Vehicles and equipment: a "move my car" or "whose forklift is this" contact that does not require reading tiny digits off a dashboard card.
- Posters and shop windows: people rarely memorize numbers off a wall; a scan carries the digits into the dialer without transcription.
- Business cards, as the fast path: alongside a full vCard code — one code to save the contact, one to call right now.
- Next to a messaging code: the same number also builds an SMS code or a WhatsApp code. The three payloads differ in scheme and encoding, and the guide linked above shows exactly how.
Phone QR code FAQ
Does it work with landlines and extensions?
Landlines, yes — any dialable number in international format works. Extensions are not reliable across handsets, so print "then dial ext. 204" next to the code instead of trying to encode it.
Why does the generator reject my local-format number?
A local number only works dialed from the same country. The code may be scanned by a tourist, a roaming phone, or someone whose handset formats calls internationally — the + form works for all of them, so the generator insists on it.
Does scanning the code place the call?
No. Scanning never dials by itself: every phone shows the number and asks for confirmation. A phone code cannot rack up premium-rate calls behind anyone’s back.
Does the generator check that the number is real?
No. The engine validates format, not truth: it confirms the input normalizes to a + followed by digits and nothing more. It cannot know whether the number is reachable, whether it is yours, or whether a digit is transposed — a wrong number encodes just as cleanly as a right one. Treat a freshly generated code as untested until a real device has scanned it.
Can I change the number after printing?
No. The number lives inside the image: the code is static, with no redirect through our servers, so it never expires and cannot be held hostage — but it also cannot be edited after printing, and scans cannot be counted. A new number means a new code.
Why does the symbol show a different error-correction level from the one I chose?
The level reported is the one actually encoded. It is never lower than the one requested, but the reference encoder raises it when doing so does not increase the version, so a short payload such as a phone number can be encoded at a higher level than asked for at no cost in size.
Can I add a logo to a phone code?
Yes. A logo overlay forces error correction H and is capped at 16% of the symbol area; the cap is decode-tested in the round-trip suite, which verifies that a worst-case logo at that size still scans. The logo decorates the image only — it is not part of the number.
Call, SMS, or WhatsApp code?
Voice for urgency and accessibility; SMS for async requests that need no app; WhatsApp where it is the dominant channel. The delivery row on each generator makes producing all three quick.
Handing over more than a number? The vCard contact code saves your whole card to their address book in one scan.