← All articles

How to Build Safe QR Code Event Tickets in 5 Steps

2026-10-02 · 4 min read

Advertisement

How to Build Safe QR Code Event Tickets in 5 Steps

Imagine a concert where three strangers walk straight through the gate because they copied a QR code from a social‑media post. The picture looked real, but there was no protection behind the black squares. That single mistake can turn a simple ticket system into a fraud‑magnet, costing organizers time, money, and reputation. In this guide we will walk you through a practical, code‑first approach that makes an ordinary QR code into a tamper‑proof ticket. The method works for a backyard gig or a stadium‑scale event.

Why QR codes need protection

When a guest scans a ticket, the whole security chain is tested. A plain QR code that only contains a seat number is easy for bots to copy. I have seen a pop‑concert where three friends printed the same QR from a public Instagram post and walked straight in. This was not a glitch; it was a lack of encryption.

Choose the right data format

Instead of putting raw text in the QR, wrap the ticket data in a signed JSON payload. JSON is a simple text format that looks like a list of name‑value pairs. A signed payload means we add a short code that proves the data has not been changed.

A typical payload looks like this (shown as JSON for clarity, but it will be encoded later):

{"event_id":"E12345","ticket_id":"T987654321","user_id":"U00123","seat":"B12","exp":1735689600}

* exp is a Unix timestamp that forces the code to expire after the event ends.
* The whole object is signed with an HMAC key that only your backend knows. HMAC is a way to create a short verification code using a secret key.
* The signature is added as a short Base64URL string. Base64URL is a way to turn binary data into readable text that is safe for URLs and QR payloads.

Using a structured payload gives you flexibility – you can add fields for tier, access level, or a one‑time discount code without changing the QR generation logic.

Generate the code securely

Below is a minimal Python script that creates a signed payload and turns it into a QR image. It uses the cryptography library for HMAC and qrcode for the visual part.

import json, base64, hmac, hashlib
import qrcode

# Keep this secret out of source control – use a vault or env var
secret = b'super-secret-key'

payload = {
    "event_id": "E12345",
    "ticket_id": "T987654321",
    "user_id": "U00123",
    "seat": "B12",
    "exp": 1735689600
}

# Serialize without whitespace for deterministic signing
data = json.dumps(payload, separators=(",", ":")).encode()
# Compute HMAC‑SHA256 signature
sig = hmac.new(secret, data, hashlib.sha256).digest()
# Encode payload and signature separately using URL‑safe Base64, then join with a dot
payload_b64 = base64.urlsafe_b64encode(data).decode().rstrip('=')
sig_b64 = base64.urlsafe_b64encode(sig).decode().rstrip('=')
signed = f"{payload_b64}.{sig_b64}"

qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M)
qr.add_data(signed)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
img.save("ticket.png")
Advertisement

The script does three things in one pass:
1. Turns the ticket data into a compact string.
2. Adds a cryptographic signature.
3. Creates a scannable QR image.

Run it on a server that never writes the secret to logs, and you already have a “safe QR code event ticket”.

Validate on the turnstile

When the scanner reads the code, the verification app should perform these steps:

  • Split the scanned string at the last . to separate the Base64URL‑encoded payload from the signature.
  • Base64URL‑decode each part (adding back any required padding).
  • Re‑calculate the HMAC using the stored secret over the decoded payload.
  • Compare the computed signature with the decoded signature using a constant‑time comparison.
  • Reject any payload where exp is older than the current Unix time.

If any step fails, the gate stays closed and an alert is logged. This works whether the scanner is an Android phone, an iOS device, or a dedicated hardware reader.

Monitor and rotate keys

No secret lives forever. Change (rotate) the HMAC key every 90 days. During a 48‑hour overlap period, keep the previous key in a read‑only table so tickets issued just before rotation remain valid. After the overlap ends, delete the old key completely. Regular rotation limits the damage of a leaked key and forces attackers to keep up with your schedule.

Step‑by‑step checklist for safe QR code event tickets

  • Define payload fields – event, ticket, user, seat, expiry.
  • Pick a strong HMAC key – at least 256 bits, stored in a vault.
  • Implement signing – use a vetted library; avoid home‑grown crypto.
  • Create the QR – set error correction to level M or higher (this adds extra dots that help the code be read even if it gets dirty).
  • Deploy verification – reject mismatched signatures instantly.
  • Log failures – include IP, timestamp, and QR hash for forensic analysis.
  • Rotate keys – automate the process; never reuse a key.

Following this list turns a simple square of black dots into a ticket that resists copy‑cats and data leaks.

Wrap‑up

The cost of a secure QR ticket is a few extra lines of code and disciplined key management. Compared with the headache of dealing with fraudulent entries, it’s a bargain. If you already use QR codes for invitations, apply the same signing routine and you’ll get a “safe QR code event tickets” system that scales from a backyard workshop to a stadium‑size production.

Advertisement
Advertisement