Skip to content
All guides

Read receipts, invoices and screenshots

Models with image input can read photos, scans and screenshots. Combined with strict JSON output you can automate expense reports, invoice entry or form processing without OCR templates.

Recommended models

Chosen from models whose abilities we have verified for this job. Cost is for one receipt photo (about 2K tokens in, 120 out), at current prices.

ModelInput / 1MOutput / 1MContextPer request
Our pickQwen3.8 Max (open weights, 2.4T A95B)
qwen/qwen3.8-2.4t-a95b
$2.50$7.501M$0.0049
Also strongKimi K3
moonshotai/kimi-k3
$3.75$18.751.05M$0.00825
Lowest costGLM 5.3 Flash
z-ai/glm-5.3-flash
$0.1875$0.6251.05M$0.000375

How it works

  1. 1Encode the image as a data URL (base64) or pass a public https URL.
  2. 2Send it as an image_url content part next to a short text instruction.
  3. 3Ask for strict JSON with exactly the fields you need, and validate amounts before booking them.

Copy, paste, run

Set AMR_API_KEY to a key from your dashboard, install the OpenAI SDK (pip install openai or npm install openai) and run it. It reads receipt.png from the current folder; use your own file. Swap the model for any other in the table.

import base64
import json
import os

from openai import OpenAI

client = OpenAI(base_url="https://api.aimodelsrouter.ai/v1", api_key=os.environ["AMR_API_KEY"])
MODEL = "qwen/qwen3.8-2.4t-a95b"

# Any JPEG/PNG works: a phone photo of a receipt, a scanned invoice, a screenshot.
with open("receipt.png", "rb") as f:
    image = "data:image/png;base64," + base64.b64encode(f.read()).decode()

schema = {
    "type": "object",
    "properties": {
        "merchant": {"type": "string"},
        "date": {"type": "string", "description": "YYYY-MM-DD"},
        "total": {"type": "number"},
        "currency": {"type": "string", "description": "ISO code, e.g. USD"},
    },
    "required": ["merchant", "date", "total", "currency"],
    "additionalProperties": False,
}

response = client.chat.completions.create(
    model=MODEL,
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Read this receipt and return the merchant, date, total and currency."},
            {"type": "image_url", "image_url": {"url": image}},
        ],
    }],
    response_format={"type": "json_schema", "json_schema": {"name": "receipt", "strict": True, "schema": schema}},
)
print(json.loads(response.choices[0].message.content))

Tested 2026-10-28: both versions were run against the live API with each model recommended at the time, and their answers checked.

Tips

  • Images count as input tokens; downscale very large photos to about 1,500 px on the long side to save cost without losing legibility.
  • Only models marked Image on their page accept images; we test every one with a real image before listing it.
  • Keep a human review step for amounts above a threshold you choose.
All 10 models that fit this job