QRsvg

Developers

QR code API

One GET request, one clean SVG. No API key, CORS enabled, cache-friendly and free within a fair-use limit of 60 requests per minute.

Endpoint

HTTP
GET https://qrsvg.app/api/qr?data=<url-encoded content>[&size=512&ecl=M&color=000000&bg=ffffff&shape=square&eye=square&margin=2&preset=<id>]

The response is image/svg+xml. Output is deterministic: the same query string always produces the same bytes, which is what makes it safe to cache aggressively at every layer.

QR code for https://qrsvg.app generated live by the API with rounded modules

Live example

This image is served by the API right now. Change the parameters in the URL and reload to see the effect.

<img src="https://qrsvg.app/api/qr?data=https://qrsvg.app&shape=rounded&size=256">

Parameters

NameTypeDefaultDescription
datastringrequiredThe content to encode, URL-encoded. Up to 2,000 characters; long payloads produce dense codes (see the size guide).
formatsvgsvgOutput format. SVG only at the moment; PNG is coming soon and will accept the same parameters.
sizeinteger 64–2048512Width and height in CSS pixels written to the SVG root. The viewBox is always module-based, so the file scales losslessly regardless.
eclL | M | Q | HMError-correction level: about 7%, 15%, 25% or 30% of the code can be damaged and still scan. Higher levels add modules.
colorhex000000Module colour as 3- or 6-digit hex without the # (e.g. 1e1b4b). A leading # is rejected with 400.
bghex | transparentffffffBackground colour (hex without #) or transparent for no background rect.
shapeenumsquareModule shape: square, rounded, dots, classy, classy-rounded, diamond, star, fluid. Finder patterns are never affected.
eyeenumsquareFinder-pattern (eye) frame shape: square, rounded, circle, leaf, shield. The eye ball follows the frame unless a preset says otherwise.
margininteger 0–82Quiet zone in modules. Use 4 for print; 0 only when you add your own padding.
presetstringApply a named design preset from the generator (colours, shapes, gradients). Explicit parameters override preset values.

Invalid values return 400 with a JSON body { "error": "...", "message": "..." }. Unknown parameters are ignored.

Examples

curl

shell
curl -o qr.svg "https://qrsvg.app/api/qr?data=https%3A%2F%2Fexample.com%2Fmenu&size=1024&ecl=Q&shape=dots&eye=rounded&color=1e1b4b&margin=4"

HTML image

html
<img
  src="https://qrsvg.app/api/qr?data=https%3A%2F%2Fexample.com&shape=rounded&size=256"
  width="256" height="256"
  alt="QR code linking to example.com"
  loading="lazy"
/>

Fetch and inline the SVG

javascript
const params = new URLSearchParams({
  data: 'https://example.com/ticket/8842',
  size: '320',
  shape: 'classy-rounded',
  color: '4f46e5',
  bg: 'transparent',
});

const res = await fetch(`https://qrsvg.app/api/qr?${params}`);
if (!res.ok) throw new Error(`QR API ${res.status}`);
const svg = await res.text();

// Inline it so it inherits page CSS and stays vector-sharp:
document.querySelector('#qr').innerHTML = svg;

Server-side (Node / Next.js route handler)

typescript
export async function GET() {
  const upstream = await fetch(
    'https://qrsvg.app/api/qr?data=' + encodeURIComponent('https://example.com') + '&size=512',
    { next: { revalidate: 86400 } }, // cache for a day on your side
  );
  return new Response(upstream.body, {
    headers: { 'Content-Type': 'image/svg+xml', 'Cache-Control': 'public, max-age=86400' },
  });
}

Rate limits

Each IP address may make 60 requests per minute. Beyond that the API returns 429 Too Many Requests with a Retry-After header (seconds). The limit is generous for rendering codes on demand and far too low for generating them in a hot loop, which is intentional: cache the result, or generate once and store the SVG. IP addresses used for rate limiting are held in memory for one minute and never persisted.

CORS and caching

  • Access-Control-Allow-Origin: * — call it from any web page, including fetch() from the browser.
  • Responses carry Cache-Control: public, max-age=31536000, immutable. Because output is deterministic, CDNs and browsers can hold it indefinitely; a different design is a different URL.
  • X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers are sent on every response, plus X-QR-Version and X-QR-Modules describing the code.

Best practices

  • Always URL-encode data. A raw & or # in a URL will be interpreted as part of the query string and truncate your payload.
  • Prefer ecl=Q and margin=4 for anything printed; keep M and margin=2 for on-screen codes. See error correction explained.
  • Dark modules on a light background scan best. If you pass a custom color, keep the contrast ratio against bg above 4.5:1.
  • Email clients do not render SVG. For HTML emails, wait for format=png or rasterise on your side.
  • Need thousands of codes, private hosting or a guaranteed SLA? The project is open source at github.com/nsilviu/qr-code-app and the same endpoint runs on your own domain.

Status and roadmap

  • Now: SVG output, all styling parameters above, presets, rate limiting, CORS, caching.
  • Coming soon: format=png (and jpeg, webp) with a scale parameter, plus a logo parameter for same-origin images.
  • Changes are announced here and on the developer guide. Breaking changes will be versioned under a new path.