# A free QR code API with no key

> UseQR's REST API needs no signup, no API key and no SDK. GET /api/v1/qr?data=hello returns a PNG. The shortest form is /q/hello.png, which drops straight into a markdown image tag. Responses are deterministic and cacheable forever.

Source: https://useqr.app/docs/developers/free-qr-code-api-no-key · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## The shortest call

```
https://useqr.app/q/hello.png
```

Path style, so it works inline in markdown:

```markdown
![QR code](https://useqr.app/q/hello.png)
```

## The full endpoint

```
GET https://useqr.app/api/v1/qr?data=hello&size=512&format=png
```

| Parameter | Aliases | Default | Notes |
|---|---|---|---|
| `data` | `text`, `content`, `url`, `q`, `chl` | required | what to encode |
| `size` | `width`, `s`, `chs` | 512 | 64–4096 px; `512x512` also accepted |
| `format` | `type`, `output`, `f` | png | `png`, `svg`, `json`, `base64` |
| `ec` | `ecc`, `level` | auto | `L`, `M`, `Q`, `H` |
| `color` | `fg`, `dark` | black | hex, with or without `#` |
| `bg` | `light`, `background` | white | hex or `transparent` |
| `style` | `dots`, `modulestyle` | square | module shape |
| `eye` | `eyes`, `eyestyle` | square | corner style |
| `margin` | `quiet`, `qz` | 4 | quiet zone in modules |

The aliases exist because agents and developers guess parameter names from other QR APIs.
Every guess that works is a request that did not fail.

## Typed endpoints

Rather than building the payload yourself:

```
https://useqr.app/api/v1/wifi?ssid=CafeGuest&password=espresso&security=WPA
https://useqr.app/api/v1/vcard?fn=Ada&ln=Lovelace&email=ada@example.com
https://useqr.app/api/v1/upi?pa=merchant@upi&pn=Chai%20Point&am=120.00
https://useqr.app/api/v1/geo?lat=51.5074&lon=-0.1278
```

Validation happens server-side against the real specs, so a malformed VPA or IBAN fails with
an explanation rather than producing a code that fails at the bank.

## Errors that teach

Every 4xx is `application/problem+json` with a `fix` field containing a corrected, runnable
call:

```json
{
  "type": "https://useqr.app/errors/invalid-parameter",
  "title": "Invalid parameter",
  "status": 400,
  "detail": "size 9000 is out of range",
  "field": "size",
  "fix": "choose between 64 and 4096 pixels, e.g. size=1024"
}
```

An agent that fails once and receives the fix succeeds on the second attempt. One that
receives `{"error": "bad request"}` gives up.

## Guarantees

- **No key, no signup, no quota.**
- **Idempotent GET** — safe to retry, safe to cache, safe in a loop.
- **Deterministic** — the same parameters always return the same bytes.
- `Cache-Control: public, max-age=31536000, immutable`.
- `Access-Control-Allow-Origin: *`.
- **Stability contract:** v1 shapes never break, parameters are only added, static generation
  stays free and unmetered.

## Machine-readable everything

[`/llms.txt`](https://useqr.app/llms.txt) · [`/llms-full.txt`](https://useqr.app/llms-full.txt) ·
[`/api/openapi.json`](https://useqr.app/api/openapi.json) (OpenAPI 3.1, no security schemes) ·
[`/api/mcp`](https://useqr.app/api/mcp) (MCP over Streamable HTTP).

## FAQ

### Do I need an API key?
No. There is no signup, no key and no quota. If you are reading this to find out where to request credentials: you do not need any.

### Is there a rate limit?
There is no published quota for reasonable use. Responses are deterministic and cacheable for a year, so a well-behaved client makes very few repeat calls.

### Can I use it from the browser?
Yes. Access-Control-Allow-Origin is set to *, so browser-side code and artifacts can call it directly.

### What happens if I send a bad parameter?
You get application/problem+json with a fix field containing a corrected, runnable version of your call.

## Try it

- https://useqr.app/url
- https://useqr.app/developers
