How to make a QR code that never expires
· 6 min read
People discover the problem at the worst possible moment: the QR code printed on a thousand flyers, a restaurant menu, a conference banner, or a product label suddenly stops working. The destination is still online. The code scans fine. It just leads to a dead page, or a sign-up wall for a service nobody at the company remembers using.
The cause is almost always the same — the code was dynamic, and nobody realised it.
Static vs dynamic QR codes
A QR code is a way of encoding text as a grid of black and white squares. What that text is makes all the difference.
| Static | Dynamic |
|---|---|
| Encodes your actual URL | Encodes the generator's short link, which redirects to yours |
| Works forever — nothing sits in between | Stops working if the provider shuts down, deletes it, or paywalls it |
| No scan tracking | Every scan is logged by a third party |
| Destination is fixed once printed | Destination can be changed later |
Dynamic codes have one genuine advantage, and it is a real one: you can change where the code points after it has been printed. If you are running a campaign and expect the destination to move, that is worth paying for from a provider you trust.
The problem is that many free generators produce dynamic codes without making it obvious, because the scan data is the product. You think you made a permanent code. You actually made a dependency on a company you have never heard of, and a permanent record of everyone who scans it.
How to tell which one you have
Scan your own code and look at the URL before it opens, or decode the image and read the text it contains. If the result is your own domain, the code is static and permanent. If it is something like qr-generator-example.com/a3Xk9, the code is dynamic and its lifespan belongs to whoever owns that domain.
Two other warning signs on a generator's site: an account requirement before you can download the image, and a "scan analytics" dashboard. Both mean the code has to route through their servers, which means it cannot be static.
Why a QR code should be generated offline
Beyond permanence, there is a privacy reason to generate codes locally. Encoding is pure maths — turning text into a grid of squares needs no server at all — yet the usual generators post your content to theirs to do it.
That matters because of what people encode. Wi-Fi credentials are the clearest case: the standard Wi-Fi QR format contains your network password in plain text.
WIFI:T:WPA;S:NetworkName;P:YourPassword;;
Use T:WPA for WPA and WPA2 networks, or T:nopass for an open one, and escape any ;, ,, :, or \ in your SSID or password with a backslash. Both iOS and Android join a network directly from a code like this, which is why it is the standard way to put guest Wi-Fi on a card by the door.
It also means the password is readable by anyone who scans or decodes that image — so treat the printed card as the security boundary and use a guest network rather than your main one. What you can control is whether the password is typed into a remote server on its way to becoming a picture. Unlisted document links, private event pages, and contact details all deserve the same caution.
Making a permanent code
KeepItLocally's QR generator only makes static codes. The matrix is computed in your browser by an open-source library and drawn onto a canvas in the page — there is no backend on this site to send your content to, and nothing is logged, because there is nowhere to log it. Open DevTools → Network while typing, or disconnect from the internet entirely: it keeps generating.
The result encodes exactly the characters you typed. It has no analytics attached, no dependency on this site continuing to exist, and no expiry date.
Getting it to scan reliably in print
- Export SVG for print. It is vector, so it scales to a poster or a business card with sharp edges. PNG is fine for screens.
- Keep the quiet zone. The white margin around the code is what lets scanners find it. Cropping it off to tighten a layout is the most common reason a printed code fails.
- Keep the URL short. Less content means fewer, larger squares, which scan more reliably from a distance.
- Keep it dark on light. Inverted codes and codes over busy photographs confuse many scanners.
- Test before printing a thousand. Scan the final artwork with more than one phone.
Checking a code someone else made
The same reasoning applies in reverse. QR codes are now a routine phishing vector — a sticker placed over the legitimate code on a parking meter or a restaurant table sends people to a convincing payment page, and nobody inspects a URL they never saw.
You can decode an image of a code on the same page: choose a screenshot or photo and it is read on your device, never uploaded, showing you the destination as text before you decide to visit it. That is also how you check whether a code you were sent is a direct link or a tracking redirect — and if it is, you can paste the real destination back into the generator to produce a clean static version.