The thing you need to read is a screenshot, not a document
Your client can look at an image. Reading a dense page end to end, in order, without dropping a line is a different operation.
What you have is a screenshot of a stack trace, or a photo of a page someone took with a phone: a little rotated, the shadow of a hand across the top, the far margin curving into the gutter.
It is not a document. There is no text layer to fail on, no pages, no container. There is an image, and the words you need are drawn inside it. Every tool that expects a file to parse has nothing to work with.
Most clients will accept the image and answer about it, which is why this failure is easy to miss. On a page with sixty lines of small print the answer comes back confident, fluent, and built on the lines that were noticed.
Looking at an image and reading it are two different jobs. A multimodal model takes in the whole frame and answers about it, which is the right operation for a diagram, a chart or a photograph of a room. Transcribing every character in reading order is not that operation. On a dense page the model works from what it attended to, attention is not exhaustive, and a line it did not attend to leaves no trace in the output. There is no gap, no ellipsis, no note that something was skipped: the sentences around the hole simply close over it.
Doing it properly yourself means an OCR engine, and on a phone photo it means everything that happens before the OCR engine. A page shot at an angle has text lines that converge instead of running parallel, so the line-finding step pairs up rows that belong to different lines and returns interleaved fragments. Shadow across the top half changes the threshold that separates ink from paper, and a fixed threshold turns the shadowed part into either solid black or blank white. This is the part that sounds like installing a package and is not.
Be honest about which case you are in. If the image is a chart, a screenshot of a user interface you want described, a whiteboard sketch or a photo of a scene, your client's own vision does that well and does it for free. This page is for the other case: the image is a page of text, and you need all of it, in order, with nothing quietly missing.
An image is uploaded and read exactly like any other file. Declaring size_bytes gets an oversized upload refused before it happens rather than after.
upload(filename="ledger-page.jpg", content_type="image/jpeg", size_bytes=2411008)
-> key, upload_url
curl -T ledger-page.jpg "<upload_url>"
read(key="<key>", mode="exact")
-> handle, engine, used_fallback, cost_eur, structure, text
result(handle="<handle>", find="ORA-01017")
-> excerpts, each with where it fallsOne image is one page. exact costs 0.016 EUR and goes straight to an engine: it is the mode for a photograph, where the reading is the hard part. balanced costs 0.007 EUR and tries local extraction first, which on an image finds nothing and then pays anyway, so the free path never saves you anything here.
Units are counted from the file, not estimated from its weight, so a single screenshot is charged as a single page whatever it happens to weigh. The same image read twice is charged once: files are recognised by their content, not by their name, which matters when every screenshot on the machine is called Screenshot 2026-08-08 at 10.14.21.
A read that fails is not charged. Every response names the engine that produced it in engine and reports in used_fallback whether the backup answered: same price, same guarantees, and never a quieter result sold as the full one.
- Handwriting, stamps and signatures are not reliably read by any engine, this one included.
- The frame has to contain the page. A photo cropped mid-sentence gives back a cropped sentence, and nothing reconstructs what was outside the shot.
- You get the text, not a description of the picture. If the question is what the chart shows or what is happening in the photo, that is your client's own vision, and it is free.
- The image is uploaded and handed to an engine that runs elsewhere. If it cannot leave your machine, this is the wrong tool.
Without markup
This page in markdown: /problems/read-a-screenshot-or-a-photo-of-a-page.md. All 20 of them in one file: /llms-full.txt.