An open specification for portable QR code redirects. Own your codes, zero vendor lock-in.
Dynamic QR codes route scans through a provider's server (provider.com/r/abc123 -> your destination). When you cancel your subscription, the redirect dies. Your printed materials — flyers, packaging, business cards, signage — become useless.
A single commercial print run costs $5,000-$40,000. The industry calls this a feature. We call it a trap.
QR Redirect Protocol (QRP) defines a simple, portable format for QR code redirect mappings. Export from any compliant provider, self-host on your own infrastructure, and your codes keep working.
Your QR codes should outlive your vendor relationship.
A QRP-compliant export is a JSON file containing all data needed to reconstruct redirects independently:
{
"qrp_version": "1.0",
"exported_at": "2026-04-13T10:00:00Z",
"provider": {
"name": "QR Nova",
"domain": "qrcodenova.com"
},
"redirects": [
{
"short_code": "a1b2c3d4",
"destination": "https://example.com/menu",
"name": "Restaurant Menu",
"type": "URL",
"mode": "DYNAMIC",
"created_at": "2026-01-15T08:30:00Z",
"total_scans": 1234,
"style": {
"fg_color": "#000000",
"bg_color": "#FFFFFF",
"pattern": "square"
}
}
]
}| Field | Type | Description |
|---|---|---|
qrp_version |
string | Protocol version (currently "1.0") |
exported_at |
string | ISO 8601 timestamp |
redirects |
array | Array of redirect objects |
redirects[].short_code |
string | The short code encoded in the QR (the path segment after /r/) |
redirects[].destination |
string | The target URL |
| Field | Type | Description |
|---|---|---|
provider |
object | Source provider info |
redirects[].name |
string | Human-readable label |
redirects[].type |
string | QR type (URL, vCard, WiFi, etc.) |
redirects[].mode |
string | STATIC or DYNAMIC |
redirects[].created_at |
string | ISO 8601 creation timestamp |
redirects[].total_scans |
integer | Lifetime scan count at export time |
redirects[].style |
object | Visual style metadata |
Once you have a QRP export, you can reconstruct the redirects on your own infrastructure. Here are minimal configurations for common platforms:
# Generated from QRP export
location /r/a1b2c3d4 { return 302 https://example.com/menu; }
location /r/x9y8z7w6 { return 302 https://example.com/contact; }const redirects = {
"a1b2c3d4": "https://example.com/menu",
"x9y8z7w6": "https://example.com/contact",
};
export default {
fetch(request) {
const url = new URL(request.url);
const code = url.pathname.replace("/r/", "");
const destination = redirects[code];
if (destination) {
return Response.redirect(destination, 302);
}
return new Response("Not found", { status: 404 });
},
};{
"redirects": [
{ "source": "/r/a1b2c3d4", "destination": "https://example.com/menu" },
{ "source": "/r/x9y8z7w6", "destination": "https://example.com/contact" }
]
}/r/a1b2c3d4 https://example.com/menu 302
/r/x9y8z7w6 https://example.com/contact 302
| Tool | Description | Status |
|---|---|---|
qrp-export |
CLI to export from QRP-compliant providers | Planned |
qrp-serve |
Minimal redirect server from a QRP file | Planned |
qrp-migrate |
Generate platform configs (nginx, Cloudflare, Vercel, Netlify) from QRP export | Planned |
| Provider | Export endpoint | Status |
|---|---|---|
| QR Nova | GET /api/v1/qr/export |
In development |
We encourage all QR code platforms to adopt QRP. If your platform supports QRP export, open a PR to add it to this list.
Why 302 and not 301? 302 (temporary redirect) allows destination changes without cache invalidation issues. 301 (permanent) gets cached by browsers and CDNs, making updates unreliable.
Does self-hosting lose analytics?
Yes. Self-hosted redirects are plain HTTP redirects with no tracking. Analytics require a server-side layer that logs scan metadata before redirecting. The qrp-serve tool (planned) will include optional basic analytics.
Can I use my own domain with my current provider? QRP is about portability after leaving a provider. For custom domains while using a provider, check your provider's custom domain feature.
- Simplicity. A redirect is a short code mapped to a URL. The spec should be trivially implementable.
- Portability. Export once, host anywhere. No proprietary formats.
- Permanence. QR codes printed on physical materials should outlive any single vendor.
- Transparency. The spec is open. Implementations are open. No lock-in by design.
This is a draft specification. We welcome feedback via issues and pull requests.
This specification is released under CC0 1.0 Universal — public domain. Implement it freely.
Created by QR Nova — QR codes that never expire.