# qart.uk > QR codes that are actually worth looking at. qart.uk generates QR art where the > artwork *is* the code, then verifies every image with a real QR detector before > offering it to you. Two products share the domain: a free pool of pre-generated > codes you can claim and point anywhere, and a paid Studio that generates custom > codes from your payload and style, priced in prepaid credits. A third tool, the > dithered photo QR generator, is free and runs entirely in the visitor's browser > with no server side at all — see the notes at the end. The fact that explains the *claim pool*, and the Studio when you ask it for a qart.uk code: the pixels encode a short qart.uk link, not your destination. So a printed code never has to change — you retarget it whenever you like and every copy already in the world follows. See "## Notes" for the surfaces where this is not true. ## Pages - [Home](https://qart.uk/index.md): The three doors — claim a free code, generate a custom one, or go make interactive art on thinkwith.pictures. - [How it works and what it costs](https://qart.uk/custom.md): The full explanation of generation, scan verification, retargeting, and credit pricing. Includes the FAQ. - [Free photo QR generator](https://qart.uk/photo-qr.md): Dither a photo into a scannable code, in the browser. No account, no upload, no endpoint — and the one thing here nobody scan-checks for you. - [The app](https://qart.uk/app/claim.md): The signed-in surface — claim pool, my codes, the Studio, credits, and library — plus the free, sign-in-less dithered photo QR mode and its knobs. - [Add this to your agent](https://qart.uk/agents.md): How to connect Cursor, Claude Code, or any MCP client. Human-readable. Anonymous tools need no token; scoped tools need OAuth — never a session cookie. ## For agents - [OpenAPI description](https://qart.uk/openapi.json): Every public and authenticated endpoint under https://qart.uk/api/. - [MCP server](https://qart.uk/api/mcp): Model Context Protocol over one POST. Dual-stack: the new JSON-only revision `2026-07-28` (`server/discover`, no SSE, GET/DELETE 405) and Streamable HTTP `initialize` for current Cursor/Claude (`2025-11-25` / `2025-06-18`; we echo the version you asked — we never upgrade initialize to 2026). Resolve and browse anonymously; claim, shuffle, retarget and run the Studio under the OAuth scopes you hold. Scoped tools appear in `tools/list` only once your token carries their scope. Human setup: https://qart.uk/agents. - [Buy one QR outright, no account](https://qart.uk/api/v1): `GET https://qart.uk/api/v1/qr?url=...` answers 402; pay from your own wallet over x402 and the paid retry returns a scan-verified QR as `image/png`. No sign-in, no credits, no redemption code to hand to a human — the wallet is the only identity involved. You are charged **only** if a real QR detector decodes the image: settlement follows the scan verdict, so a request that produces nothing scannable costs nothing. Style keys are at `https://qart.uk/api/v1/styles`; the live price is in the 402 at `https://qart.uk/api/v1`. - [OAuth metadata](https://qart.uk/.well-known/oauth-authorization-server): RFC 8414. Dynamic client registration is open; PKCE S256 required. - [A2A agent card](https://qart.uk/.well-known/agent-card.json): Agent-to-agent discovery. - [How to authenticate](https://qart.uk/.well-known/auth.md): OAuth 2.1 with PKCE — register a client, get the user's consent, act on their account with scoped tokens. ## Notes - Free pool allowances are 5 shuffles and 3 claims per UTC day, per account. They are not purchasable. - Studio pricing is prepaid credits: one credit is one image at the standard recipe (32 sampling steps, 768px). More steps or higher resolution costs proportionally more, quoted before a run starts. - You are charged only for images actually produced. Stopping a run refunds the unused reserve; a run that produced nothing refunds in full. - **Not every surface mints a qart.uk link, and that decides whether a code is retargetable.** A claimed pool code always does. A Studio run does only when you pick the `qart.uk code` payload kind; every other kind (url, wifi, vcard, mecard, text, mailto, tel, sms, geo, whatsapp, telegram, event, and social wrappers) is encoded verbatim. The agent API at `/api/v1` and the free dithered photo QR tool never do. A code that carries your destination directly does not depend on us staying up — and equally, it can never be retargeted. If you want a code you can re-point later, claim a pool code or run the Studio on the `qart.uk code` kind. - **There is a free dithered photo QR generator, and it has no API — there is nothing here for an agent to call.** It is a browser-only tool at `https://qart.uk/photo-qr` (also the "Dithered photo QR" mode switch inside `https://qart.uk/app#/studio`, the same document): a photo is error-diffused into the gaps between the QR modules and the result is a 1-bit PNG you download. It touches no server of ours — no endpoint, no account, no credits, no sign-in, and nothing is stored. So it cannot be driven over HTTP, MCP, A2A or x402, and it is absent from `openapi.json` on purpose rather than by oversight. Send a human to the page. Details, knobs and caveats are in [llms-full.txt](https://qart.uk/llms-full.txt) and on [the app page](https://qart.uk/app/claim.md). - **The dithered tool is the one place on qart.uk where nothing is scan-verified.** Everything else is decoded by a real QR detector before it is offered; that check runs on our GPU host, and this tool never reaches it. Its output is unverified by construction — see llms-full.txt before you promise a user it will scan. - Cursor mcp.json (anonymous): `{ "qart-uk": { "type": "http", "url": "https://qart.uk/api/mcp" } }` - Claude Code: `claude mcp add --transport http qart-uk https://qart.uk/api/mcp` - Human setup: https://qart.uk/agents - qart.uk is operated by the same people as [thinkwith.pictures](https://thinkwith.pictures), the game it grew out of. --- # Home qart.uk — QR codes that are actually worth looking at. Three doors: 1. **I just want a cool QR code linking somewhere.** Pick one that already exists, point it at your URL. Free. → https://qart.uk/app/claim 2. **I want a custom QR code with full control of the metadata and I have a budget.** Your destination, style, print size, and regime — we generate until it scans. Paid. → https://qart.uk/app#/studio 3. **I want to make cool interactive art.** thinkwith.pictures, the game this grew out of. → https://thinkwith.pictures --- # Custom QR code art that still scans Most "designer" QR codes are a logo dropped in the middle of a normal code. These are the other way round: the artwork *is* the code, generated against your payload and then checked with a real scanner before you ever see it. ## How it works 1. **Say what it should encode.** A web address, WhatsApp, a calendar event, a Wi-Fi network, a contact card, a social profile, or plain text. The Studio assembles the payload and shows you the exact string the pixels will carry. 2. **Say what it should look like.** Pick a style from the catalog or describe your own, then set the balance between QR-forward and art-forward, the print size, and the quiet zone around the code. 3. **Generate until it scans.** Images stream in as they finish, each one already decoded and verified against your payload. Keep the ones you like; stop whenever you have enough. ## What it costs Prepaid credits, no subscription. One credit is one image at the standard recipe; more sampling steps or a higher resolution costs proportionally more, and the Studio prices the run before you start it. A run holds a small reserve while it is generating and hands back whatever it does not use when you stop. Current pack prices are shown at https://qart.uk/app#/credits. They are deliberately not restated here — Stripe is the source of truth and a second copy would drift. ## Or take one that already exists — free The claim pool is a gallery of finished codes looking for a destination. Pick one, point it at your URL, and change that destination whenever you like. No credits, no card. ## Questions ### Will an AI-generated QR code actually scan? Every image is checked by a real QR detector - the same WeChat detector that ships inside scanner apps - and each one carries its verdict. What differs is what happens to the ones that fail. The free claim pool only ever offers codes that passed. The Studio sells GPU time rather than scans: it shows you every image it generates, passed or failed, labelled either way, and charges for the generation - so expect to pick the good ones out of a run rather than to get a run of only good ones. The pay-per-code agent API is the strict one: it returns an image only if the detector decoded it, and only charges you then. The free dithered photo QR tool runs entirely in your browser and is never checked by us at all - test that one before you print it. ### Can I change where the code points after it is printed? That depends on which kind you asked for, so choose before you print. Claim a pool code, or run the Studio on the "qart.uk code" payload kind, and the pixels encode a short qart.uk link rather than your destination - retarget it whenever you like and every copy already in the world follows. Every other payload kind (a web address, Wi-Fi, a contact card, plain text), the agent API, and the dithered photo tool all encode exactly what you gave them. Those codes do not depend on us being here in ten years, which is the trade - but they can never be re-pointed. ### What can the code contain? A web address, WhatsApp, Telegram, a calendar event, a Wi-Fi network, a contact card, a social profile, email, phone, SMS, a location, or plain text. You fill in a small form per kind and the Studio assembles the payload the pixels encode. Only the qart.uk code type stays retargetable after printing. ### How is it priced? Prepaid credits, and the unit is deliberately simple: one credit is one image at the standard recipe. Turning the quality knobs up costs proportionally more, and the price per image is shown before a run starts, so nothing is a surprise. ### What happens if I stop a run early, or it fails? You are only charged for images that were actually produced. Stopping returns the unused part of your reserve to your balance, a run that never produced an image refunds in full, and anything that breaks on our side refunds in full. ### Is there a free option? Yes. The claim pool is a gallery of codes that already exist and already scan. Take one, point it at your URL, and retarget it later - no credits involved. --- # Dithered photo QR — free, and there is no endpoint The second mode of the Studio view. A photo is error-diffused into the gaps between the QR modules, so the module centres still carry the payload while the rest of the square becomes a one-bit picture; the output is a 1-bit PNG you download. It is a port of andrew-t's technique (https://www.andrewt.net/dithered-qr-codes/). **All of it runs in the browser.** No cf-api call, no GPU, no credits, no sign-in, no database, nothing stored. That is not a temporary state of the rollout — there is no endpoint to call, no MCP tool, no A2A skill and no x402 price, and none is planned. An agent's only useful move here is to send a person to `https://qart.uk/photo-qr`, which is this tool's own page and opens directly in it. It is also reachable as the second mode of `https://qart.uk/app#/studio`, the same document, if a person is already in the app. Neither route depends on the paid Studio being switched on: the tool needs nothing that switch controls. The Data panel is shared with the AI run: payload kind (url, wifi, vcard, mecard, text, mailto, tel, sms, geo, whatsapp, telegram, event, and social wrappers — the `qart.uk code` kind is hidden here because minting an alias needs a server), ECC (L/M/Q/H, default **H**), mask (`auto` or a pinned 0–7 — never `random`, which only means anything when a run produces many images), version (`auto` or 1–40), quiet zone (1–10 modules, default 4), and an invert toggle. The photo panel adds: | Knob | Range | Default | |---|---|---| | Photo (required) | PNG, JPEG or WebP, up to 6 MB | — | | Gamma | 0.01–10 | 2.2 | | Contrast | 0.01–10 | 1 | | Brightness | −0.5 to 0.5 | 0 | | Min brightness | 0–1 | 0.05 | | Max brightness | 0–1 | 0.95 | | Subpixel ratio | 3–6 (integer) | 4 | | Rotation | 0°, 90°, 180°, 270° | 0° | | Mirror QR | on/off | off | | Fudge worst data pixels | 0–0.05 | 0 | | Diffuse data points | on/off | off | | Diffuse free points | on/off | on | | Lock finder patterns | on/off | on | | Lock timing lines | on/off | on | | Lock alignment markers | on/off | on | **Every code is decoded before the result is described, in the same browser.** The tool loads a QR decoder (jsQR) on the first generate and reads back the exact PNG the download button gives you, then shrinks that image until it stops decoding — the reported percentage is the closest available proxy for how far a phone can be. Nothing is uploaded and no verdict is stored; this stays a zero-server tool. A verdict is a real check, not a guarantee: it is one decoder on a clean bitmap, not a camera pointed at ink. Two specifics worth passing on to anyone tuning this. **Subpixel ratio 4 is the one that works**, and the reason is structural rather than aesthetic: an even ratio leaves each module a 2×2 core carrying its true value (4 subpixels of 16), an odd ratio leaves a single centre pixel (1 of 9 at ratio 3, 1 of 25 at ratio 5). Swept over six photographs and two gammas against an independent decoder, ratio 4 decoded 12/12 while ratios 3, 6 and 5 managed 3, 4 and 1. **Diffuse data points** dissolves the modules into the photo and defaults **off**, because that costs robustness: at ratio 4 the two settings tie under zbar (12/12 each) but split under jsQR, 7/8 off against 6/8 on, and off carries the better shrink margin under both (median 25% against 33%). It is worth turning on anyway — it is the better-looking result and the verdict will say immediately whether that particular photo could afford it. Fudge flips the worst few data modules to buy image quality and can render the code unreadable — leave it at 0 unless you are testing. Historical note, because it is the reason any of the above is written down: from launch until 2026-08-15 this tool rendered every code in **reverse polarity** (the encoder returns isDark(), the dither pipeline reads true as light), so the output was a photographic negative of a QR. zbar decoded 0 of 8 configurations. It survived because the only decoder anywhere near this feature was the Modal WeChat gate, which tolerates inverted codes, and the free tool never touched it. --- # Add this to your agent qart.uk speaks MCP. Point Cursor, Claude Code, or any Streamable HTTP client at the endpoint below and it can resolve scanned codes, browse the free claim pool, and — with OAuth scopes the user consents to — claim codes and run the Studio. Canonical HTML page: https://qart.uk/agents ## Endpoint `https://qart.uk/api/mcp` POST only. GET returns 405. No SSE, no sessions (`Mcp-Session-Id` is never minted). Protocol `2026-07-28`: modern clients send `server/discover` plus `MCP-Protocol-Version` / `Mcp-Method` / `Mcp-Name` headers; current Cursor may still send `initialize`. Agents that crawl should start at [https://qart.uk/llms.txt](https://qart.uk/llms.txt). ## Anonymous — no account, no header These tools work with no `Authorization` header: `resolve_qart_code`, `browse_free_pool`, `preview_qr_encoding`, `get_qr_matrix`, `get_dither_qr_parameters`, `get_credit_packs`, `buy_qr_outright`, `explain_qart`. ### Cursor Settings → MCP, or paste into `~/.cursor/mcp.json`: ```json { "qart-uk": { "type": "http", "url": "https://qart.uk/api/mcp" } } ``` ### Claude Code ``` claude mcp add --transport http qart-uk https://qart.uk/api/mcp ``` ## To act as a signed-in user **Do not paste a qart.uk session cookie.** It is an HttpOnly, unscoped, 30-day credential. JavaScript on this site cannot read it, you should not copy it out of the browser, and the MCP server rejects it outright. Your agent registers as an OAuth client and sends the user through consent. Access tokens last 1 hour; refresh tokens last 30 days and rotate. Full flow: [https://qart.uk/auth.md](https://qart.uk/auth.md). Scopes: `qart:profile`, `qart:read`, `qart:claim` (daily allowance), `qart:studio` (spends prepaid credits), `qart:purchase` (agent pays for credits from its own wallet). Ask for the least you need. Treat an access token like a password. Anyone holding `qart:studio` can spend that account's credits; anyone holding `qart:claim` can claim and retarget their codes. ### Cursor (after OAuth) ```json { "qart-uk": { "type": "http", "url": "https://qart.uk/api/mcp", "headers": { "Authorization": "Bearer " } } } ``` ### Claude Code (after OAuth) ``` claude mcp add --transport http qart-uk https://qart.uk/api/mcp --header "Authorization: Bearer " ``` ## What will not work over MCP - Driving the SPA, including the free dithered photo QR tool (no server side). - Redeeming coupons or enabling adult content (browser-only, deliberately). - Charging the user's saved card. An agent that wants more credits pays itself (`qart:purchase` or `GET https://qart.uk/api/v1/qr`).