You need a QR code in an app, an email, a ticket PDF, a poster, a terminal script โ and you don't want to vendor a QR library into every codebase, run an image service, or paste strings into a generator website one at a time. The URL-parameter pattern solves this: put your data in a query string, get image bytes back, and let an <img> tag or a curl -o do the rest.
Mockbird serves QR codes exactly that way โ no key, no signup, no watermark, and the same URL returns the same bytes forever, so caches and CDNs love it:
# a scannable 256x256 PNG โ this URL works right now
curl -o qr.png "https://mockbird.mockbird.workers.dev/m/demo/qr?data=https%3A%2F%2Fexample.com"
# bigger, with a size in the path
curl -o qr.png "https://mockbird.mockbird.workers.dev/m/demo/qr/500?data=hello+world"
# vector output for print (crisp at any scale)
curl -o qr.svg "https://mockbird.mockbird.workers.dev/m/demo/qr.svg?data=hello+world"
Or straight in HTML โ the classic use:
<img src="https://mockbird.mockbird.workers.dev/m/demo/qr?data=https%3A%2F%2Fexample.com"
width="256" height="256" alt="QR code">
| Param | What it does | Default |
|---|---|---|
data | The payload โ URL, text, wifi string, anything. โค1000 chars, UTF-8. Aliases: text, url. URL-encode it. | required |
size / /qr/:size | Output size in px, square. 64โ2000. | 256 |
format=svg / .svg | Vector output instead of PNG โ crisp at any print size. | PNG |
ecc | Error-correction level L/M/Q/H. Higher survives more damage (logos, smudges) but fits less data. | M |
margin | Quiet zone in modules, 0โ16. The spec minimum for reliable scanning is 4. | 4 |
fg / bg | Colors, 3- or 6-digit hex without #. Keep dark-on-light โ many readers fail on inverted codes. | black / white |
# a URL (the 95% case)
โฆ/qr?data=https%3A%2F%2Fexample.com%2Fmenu
# wifi credentials (scan โ join network)
โฆ/qr?data=WIFI%3AT%3AWPA%3BS%3Amynet%3BP%3Asecret123%3B%3B
# mailto / tel
โฆ/qr?data=mailto%3Ahello%40example.com
โฆ/qr?data=tel%3A%2B15551234567
# plain text (event check-in codes, ticket ids)
โฆ/qr?data=TICKET-2026-000451
Encoding tip: always URL-encode the payload. &, ?, #, + and spaces inside an unencoded data= will be eaten by query parsing โ encodeURIComponent() in JS, urllib.parse.quote() in Python, --data-urlencode with curl.
> for id in 001 002 003; do
curl -s -o "ticket-$id.png" \
"https://mockbird.mockbird.workers.dev/m/demo/qr/400?data=TICKET-$id&ecc=Q"
done
Because output is deterministic, re-running the loop produces byte-identical files โ safe for build pipelines and reproducible artifacts.
| Mockbird | goqr.me (api.qrserver.com) | QuickChart /qr | a QR library | |
|---|---|---|---|---|
| Key / signup | none | none | none | n/a |
| PNG | โ | โ (+ GIF/JPEG/EPS) | โ | depends |
| SVG | โ | โ | โ | depends |
| Free volume | generous per-project daily cap | informal ~10k/day courtesy | 1,000 renders/month, 60/min | unlimited (your CPU) |
| Center logo image | โ | โ | โ | some |
| Decode/read API | โ | โ | โ | some |
| Deterministic bytes | โ | not guaranteed | not guaranteed | โ |
| Also a full mock REST API | โ | โ | โ | โ |
Being upfront: goqr.me has run a solid free QR endpoint for over a decade and also reads QR codes โ if you need decoding or EPS output, use it. QuickChart is open-source (you can self-host the AGPL server) and supports embedding a center logo image, which we don't. Mockbird's angle: the QR endpoint lives next to your mock REST API, placeholder images, avatars and OG cards under one project URL โ one host to remember for everything a frontend needs before the real backend exists. And offline/air-gapped builds should always vendor a library instead of calling anyone's API.
Seeded mock data + QR endpoint composes nicely: render a QR per record with nothing but string interpolation.
// e.g. a ticket list from the demo API, each with its own QR
const res = await fetch("https://mockbird.mockbird.workers.dev/m/demo/orders?limit=5");
const orders = await res.json();
document.body.innerHTML = orders.map(o =>
`<img src="https://mockbird.mockbird.workers.dev/m/demo/qr/160?data=ORDER-${o.id}" width="160">`
).join("");
data capped at 1000 characters. QR byte-mode capacity is 2,953 bytes at ecc=L and 1,273 at ecc=H โ 1000 ASCII chars fit at every level; heavy multi-byte UTF-8 can overflow at high ECC (the error says so โ drop to ?ecc=L or shorten).?format=svg for larger.size is smaller than one pixel per module, you get a 400 telling you the minimum.demo project and work forever. Want your own namespace (and a full mock REST API + placeholder/avatar/OG endpoints alongside it)? One click creates a project โ no signup.Full reference in the docs. More image guides: placeholder image API ยท PNG placeholder API ยท OG image API ยท chart image API ยท avatar API ยท identicon API. Create your API โ