Skip to content
QRBeam

QR code API

One endpoint, no API key, no account. Send your content and get an SVG back. Free for reasonable use.

Endpoint

GET https://qrcodebeam.com/api/qr?data=hello

The response is image/svg+xml, so the URL can go straight into an <img> tag:

<img src="https://qrcodebeam.com/api/qr?data=https%3A%2F%2Fexample.com&size=320"
     width="320" height="320" alt="QR code" />

Remember to URL-encode the data value. A raw & or # inside your content will otherwise be read as part of the query string.

Parameters

NameValuesDefaultDescription
datastringrequiredThe text to encode. Any string — a URL, a WIFI: payload, a vCard. Use /api/mcp's build_qr_payload, or the format tables in /api-docs, to construct structured payloads.
size64–2048512Width and height of the rendered SVG, in pixels.
eccL | M | Q | HMError correction level. L recovers ~7% of a damaged symbol, M ~15%, Q ~25%, H ~30%. Higher levels make the symbol denser.
margin0–164Quiet zone width in modules. Four is the specification minimum; below that, scanners struggle to find the symbol.
darkhex colour#0f172aColour of the dark modules.
lighthex colour#ffffffBackground colour.
dotStylesquare | rounded | dots | classysquareModule shape.
eyeStylesquare | rounded | circle | leafsquareFinder pattern shape.
transparentbooleanfalseOmit the background rectangle entirely.

POST

Long payloads are easier to send as JSON. The body takes the same fields as the query string.

curl -X POST https://qrcodebeam.com/api/qr \
  -H 'Content-Type: application/json' \
  -d '{"data":"WIFI:T:WPA;S:Cafe;P:hunter2;;","ecc":"Q","size":600}' \
  -o wifi.svg

Embedding from your own site

The endpoint sends Access-Control-Allow-Origin: * and Cross-Origin-Resource-Policy: cross-origin, so the <img> tag above works from any domain, and fetch() from your own front end works too. A JSON POST triggers a preflight, which the endpoint answers on OPTIONS.

Limits

  • 60 requests per minute per IP. Over that you get a 429 with a Retry-After header.
  • Payload capped at 2000 bytes; request bodies capped at 8 KB. The body cap is enforced while reading the stream, so it applies to chunked requests that send no Content-Length.
  • Successful responses are cacheable for an hour at the browser and a day at the CDN. Errors are no-store.

Errors

  • 400 — a parameter failed validation. The body lists which field and why.
  • 413 — request body too large.
  • 422 — the content is valid but cannot be encoded, usually because it exceeds QR capacity.
  • 429 — rate limited.

What the API deliberately does not do

There is no logo parameter. Accepting a logo would mean taking a URL and fetching it server-side — a server-side request forgery risk — or accepting arbitrary uploaded bytes to embed in a returned document. Neither is worth it. Logos are a browser-side feature, where the file never leaves your machine.

PNG is not offered either; rasterising server-side needs a canvas implementation the serverless runtime does not have. Convert the SVG locally, or use the browser tool, which exports PNG and WebP directly.

Machine-readable definitions

If you are pointing a script, a code generator or a language model at this API, read these rather than this page. Both are generated from the same source as the running handler, so they cannot drift from it.

  • /openapi.json — the OpenAPI 3.1 contract: every parameter, its bounds, the response types and each error shape.
  • /capabilities.json — the payload formats for all ten QR types, with the required and optional fields for each. The API takes data as an opaque string; this is how you build that string.
  • /llms.txt — a plain-text index of the whole site.

MCP server

There is also a Model Context Protocol server at https://qrcodebeam.com/api/mcp, which exposes the generator as tools an AI assistant can call directly. It sits alongside this API rather than replacing it — an MCP tool result cannot be embedded as an <img> in a page, which is what this endpoint is for.

The most useful tool is build_qr_payload: Wi-Fi separator escaping, vCard structure and iCalendar wrapping are fiddly enough that models routinely get them wrong from memory, and it produces the same strings the site itself uses.

{
  "mcpServers": {
    "qrbeam": {
      "type": "http",
      "url": "https://qrcodebeam.com/api/mcp"
    }
  }
}