EPC QR Codes — The EU's Scan-to-Pay Standard for Bank Transfers

If you've ever received an invoice in Germany, Belgium, or the Netherlands and noticed a QR code in the corner that your banking app could scan to pre-fill a transfer — that's an EPC QR code. It's a quiet little standard that does something genuinely useful: eliminates the typo-prone ritual of manually entering an IBAN, amount, and payment reference.


What It Is

The EPC QR code (European Payments Council Quick Response Code) is an open standard for encoding a SEPA Credit Transfer (SCT) into a QR code. You put it on an invoice, a donation page, or a point-of-sale display. The payer scans it with their banking app; the app pre-fills the recipient's IBAN, name, amount, and payment reference. They confirm. Done.

The European Payments Council published the first version in February 2013. The latest version is 2.10, published June 2024. It's also called Girocode in Germany and Zahlen mit Code ("Pay with Code") in Austria.

Countries where banking apps actively support it:

Support is patchy elsewhere in the SEPA zone — the standard exists, but not every bank has built the scanner into their app.


The Format

The QR code contains plain text, newline-delimited, in a fixed field order. That's it. No JSON, no binary, no encryption. Just a structured text payload that any QR generator can produce.

Here's what a real payload looks like — a €1 payment to the Red Cross of Belgium:

BCD
001
1
SCT
BPOTBEB1
Red Cross of Belgium
BE72000000001616
EUR1.00
CHAR

Urgency fund
Sample EPC QR code

Line by line:

Line Field Example Notes
1 Service Tag BCD Always BCD. Identifies this as an EPC QR code.
2 Version 001 or 002 001 = BIC required; 002 = BIC optional
3 Character set 1 1 = UTF-8 (most common)
4 Identification SCT Always SCT (SEPA Credit Transfer)
5 BIC BPOTBEB1 Beneficiary bank's BIC. Optional in v2 within SEPA area.
6 Name Red Cross of Belgium Beneficiary name, max 70 characters
7 IBAN BE72000000001616 Beneficiary account, max 34 chars
8 Amount EUR1.00 EUR + amount, e.g. EUR12.50. Max: EUR999,999,999.99. Omit for open amounts.
9 Purpose CHAR Optional 4-char purpose code (e.g. CHAR = charitable donation)
10 Structured ref (empty) ISO 11649 creditor reference (structured). Mutually exclusive with line 11.
11 Unstructured ref Urgency fund Free-text payment reference, max 140 chars
12 Beneficiary info Sample EPC QR code Optional note from payee to payer, max 70 chars

Key rules:


Version 1 vs Version 2

Version 1 requires a BIC. Version 2 (released 2016) makes BIC optional within the SEPA zone, since any bank within SEPA can route to an IBAN alone. For new implementations, always use version 2 — less data means a less dense QR code, which is easier to scan.


Character Sets

The spec supports 8 character sets, encoded as an integer on line 3:

Code Encoding
1 UTF-8
2 ISO 8859-1 (Latin-1)
3 ISO 8859-2
4 ISO 8859-4
5 ISO 8859-5
6 ISO 8859-7 (Greek)
7 ISO 8859-10
8 ISO 8859-15

Use 1 (UTF-8) unless you have a specific reason not to.


Generating One in Code

It's basically a string concatenation job. Here's the core in JavaScript:

function buildEpcPayload({ bic = '', name, iban, amount, ref = '', info = '' }) {
  const version = bic ? '001' : '002';
  const amountStr = amount != null ? `EUR${Number(amount).toFixed(2)}` : '';
  
  const lines = [
    'BCD',        // service tag
    version,      // version
    '1',          // UTF-8
    'SCT',        // identification
    bic,          // BIC (or empty)
    name,         // beneficiary name
    iban,         // IBAN
    amountStr,    // amount (or empty for open)
    '',           // purpose code (omitted)
    '',           // structured reference (omitted)
    info || ref,  // unstructured reference or info
  ];
  
  return lines.join('\n');
}

Feed that string into any QR library (qrcode.js, python-qrcode, etc.) and you're done.

For open-amount invoices — where the payer enters the amount themselves — omit the amount field entirely (empty line 8). Some banking apps support this; others don't.


The Amount Field Quirks

A few gotchas:


Why It's Not Everywhere

The EPC QR standard is SEPA-wide — 36 countries in scope — but bank app support is concentrated in the 5 countries above. A few reasons:

  1. No mandate: EPC published guidelines, not a requirement. Banks adopt it voluntarily.
  2. Competing standards: Finland has its own variant (via FFI). Belgium has a structured creditor reference variant ("OGM/VCS"). These are compatible but slightly different in usage.
  3. App investment: Building and maintaining QR scanning in a banking app isn't free. Smaller banks deprioritise it.
  4. Consumer education: If nobody knows the code exists, nobody asks for it.

That said, adoption has been quietly growing. German banks in particular have pushed Girocode hard — it's common on invoices from small businesses and freelancers there.


Practical Uses

Invoices — the main use case. Put an EPC QR alongside your bank details. Your client in Germany or the Netherlands scans it, all fields pre-fill, they confirm. Faster for them, fewer wrong-IBAN calls for you.

Donation pages — charities in Belgium and Austria have used these for years. Print on a flyer, scan at an event.

Point of sale — display a QR at a market stall or café for bank transfer payments. Not as instant as card, but zero fees compared to Stripe.

Invoicing software — most European invoicing tools now auto-generate these. If yours doesn't, it should.


Online Generators

The epc-qr.eu API is genuinely handy for dynamic server-side generation — you can hit it with query params and get a PNG back directly.


The Bottom Line

EPC QR codes are a small, elegant piece of EU payments infrastructure that doesn't get nearly enough attention. The format is simple to understand and trivial to implement. If you're building invoicing tools, payment pages, or anything that involves asking someone in the SEPA zone to transfer money — add one. It takes 20 lines of code to generate and eliminates an entire category of "I mistyped the IBAN" support tickets.

← All posts