Which cloud model reads handwriting best, and what a page costs

Tagged Sync can send a page of your handwriting to a cloud model and bring the text back into Obsidian. It does not tell you which model to use. Until now I could not have told you either, because the only handwriting I had measured against was my own, fifteen pages of it, every night. This article is a handwriting OCR test that changes that: seven cloud AI models from Google, Anthropic, OpenAI, Alibaba and DeepSeek, and the model the plugin can download for you, read the same 264 handwritten pages from three public sets, with the request exactly as version 1.8.4 of the plugin sends it, and every page was billed by the provider as it would bill you.
The short version, for Tagged Sync users who do not want the rest:
- Gemini 3.1 Flash-Lite is the one to set. It read tablet ink, scanned paper and phone photos as well as anything near its price or better, and a page cost 0.046 cents, which is a dime a month at my volume.
- Claude Haiku 5.5 costs the same per page and is the one to set if you copy published text by hand, because Gemini refuses a page it recognises, and in version 1.8.4 such a page arrives blank.
- Gemini 4 Argon halves the errors on scanned paper at eight times the price and did not read tablet ink better.
- The model the plugin downloads costs nothing and reads tablet ink about as well as Haiku.
Why measure at all
On 7 October Anthropic released Claude Haiku 5.5 at a twentieth of the price of Claude Sonnet 5.5. I ran it over my fifteen reference pages the same week and could not tell the two apart. Good for my wallet. But it raised a question the nightly cannot answer, because my fifteen pages are one hand, one pen, one tablet. A reader of this site writes differently from me, and so does the next one. A recommendation built on my notebook alone would be a recommendation for me.
So the plan was to find handwriting sets that are not mine, with many writers, that I am allowed to send to a commercial API and show on a commercial website. Then read them with the plugin’s own request, score every page, and read the bill.
The three reference sets, and why these
The licence was the first filter and the hardest. Most handwriting datasets a search turns up, the IAM database above all, are “non-commercial research purpose only”. Sending them to a paid API on behalf of a product and printing a sample here is neither. Of the thirty-odd sets I checked, these two were the ones with many writers, modern Latin-script notes, text ground truth, and a licence that permits exactly this:
GNHK, the GoodNotes Handwriting Kollection, is 687 phone photos of English everyday notes, shopping lists, diaries, lecture notes, collected by Goodnotes and published under CC BY 4.0 with an ICDAR 2021 paper. No writer contributed more than five pages, so the 172 pages of the test split, the ones I used, come from well over a hundred hands. The photos are what they sound like: perspective, shadows, ruled paper, a bedspread in the background. The ground truth is word by word, with the line each word sits on, so a page’s text can be put back together.

GNHK page eng_AS_018. Goodnotes, GNHK dataset, CC BY 4.0.
The ScaDS.AI German Full-Page Handwriting Dataset is 77 half-page sheets, each a German Wikipedia paragraph copied out by a different volunteer at ScaDS.AI in Leipzig and Dresden. It was published on Zenodo in January 2026 under CC BY 4.0, with one plain-text file per page. The sheets are scanned, flat and clean, and they are German. That matters for a plugin whose author and many of whose users write German with English mixed in.

ScaDS.AI page 010. ScaDS.AI German Full-Page Handwriting Dataset, CC BY 4.0.
The third set is the plugin’s own: the fifteen reference pages the nightly reads, published in the plugin’s repository. They are fifteen pages written on a reMarkable Paper Pro, each with one trait, clean prose, rushed prose, a bulleted list, a numbered list, a table, a formula, mixed German and English, a diagram, a nearly empty page, dense writing, numbers, special characters, corrections, a margin note, and a page scrolled far past its first screen. The ground truth is a Markdown file per page. It is the only set of the three that is rendered tablet ink, which is what the plugin actually sends. The catch is that it is one writer, me.

What no public set offers is many writers and tablet ink under a licence that allows this use. The digital-ink sets that exist, IAM-OnDB, IAMonDo, BRUSH, are all research-only. So the ranking and the price come from paper, the tablet condition comes from one hand, and the article says so wherever it matters.
What is measured
Three numbers per model carry the argument; the table adds a few more for the curious.
The first is the character error rate, on the German scans and on my fifteen pages. Each transcript is compared with the ground truth character by character; the number is how many characters would have to be inserted, deleted or changed to turn one into the other, divided by the length of the truth. Both sides are normalised the way the nightly’s scorer normalises them, so a different quotation mark is not an error and a wrong letter is. Zero is perfect; 1 % means one wrong character in a hundred, roughly one per line. I report the median over the pages of a set, because otherwise one disastrous page would hide a good model behind one bad number.
The second is word recall, on the phone photos. GNHK labels only the handwritten words; the printed form headings and the stray marks on the photo are not in the truth, but every model reads them anyway, and a character error rate would punish a model for reading what is there. So for this set the question is the one the dataset can answer: of the labelled words, how many arrived in the transcript? 100 % means every word is there.
The third is cents per page, as billed: what the provider charged for each request, read off the response, summed over the 264 pages and divided by 264. This number includes the model’s thinking and the provider’s image tokenisation, which a price list leaves you to work out.
Two more things come along for free and are in the text where they matter: pages a model did not read at all, and whether a list or a table on my pages came back as a list or a table.
How it was measured
The request is the one Tagged Sync 1.8.4 sends. Nothing was tuned for the test.
- One page goes in one request to the provider’s chat completions endpoint, up to four pages in flight. The body carries the model name, the prompt and the image, and nothing else: no temperature, no token limit, no thinking setting. So every provider ran at its own defaults, thinking included. The plugin does this on purpose, because nine current Claude models answer a non-default temperature with an error. It also keeps the measured price honest. A model that thinks before it answers is billed for the thinking, and the table shows how much.
- The prompt, verbatim: “Transcribe the handwritten text in this page image into clean Markdown, preserving reading order and visible structure: headings, lists, GFM task lists (- [ ] / - [x]), and tables. Do not invent structure that is not visually present; when unsure, use plain paragraphs. Output only the transcript text – no commentary, preamble, code fences, or page labels. If the page has no legible text, output nothing.”
- My fifteen pages were drawn by the plugin from the reMarkable’s stroke files into a white, grayscale PNG at the tablet’s own pixel scale, cropped to the ink; a page scrolled far past one screen is cut into pieces, as the plugin cuts it. The 249 public pages went as the JPEG files they are, with the phone photos brought to 2000 pixels on the long edge, the size the plugin’s own images have.
- Every model went through OpenRouter, pinned to one endpoint with fallbacks switched off, so the bill and the behaviour are the model maker’s own: Google AI Studio for the two Flash-Lites, Anthropic for Haiku, OpenAI for Luna, Alibaba for Qwen, Google Vertex for Gemini 4 Argon, and DeepInfra for DeepSeek, because DeepSeek’s own endpoint is closed to accounts with OpenRouter’s stricter data-policy setting. The cost per request is OpenRouter’s accounting of the upstream charge, asked for with the request.
- Each model ran once, on 16 October 2026. Cloud models are not deterministic. A difference of a few tenths of a point between two models is a coin toss, a difference of a point is not.
- The local model ran through the same code path the plugin uses: the pinned llama.cpp build (b10295) with Qwen3-VL-8B-Instruct in Qwen’s own 4-bit GGUF, temperature 0, a fixed seed, 1 024 answer tokens, an 8 192-token context, one process per page, on an Apple M5 Max with 128 GB. The plugin’s published figure for this model was measured on an M2 Max with 64 GB; on the fifteen pages the two machines agree to the last digit.
Handwriting OCR results: error rate and cost per model
| model | German scans, CER | English photos, words found | reMarkable pages, CER | lists and tables kept | ¢ per page | thinking tokens per page | seconds per page | pages not read |
|---|---|---|---|---|---|---|---|---|
| Gemini 4 Argon | 0.23 % | 95.6 % | 2.24 % | 3/3 | 0.368 | 1 | 6.1 | 3 |
| Gemini 3.1 Flash-Lite | 0.54 % | 95.0 % | 1.00 % | 3/3 | 0.046 | 0 | 1.8 | 8 |
| Gemini 3.5 Flash-Lite | 0.64 % | 95.1 % | 2.56 % | 3/3 | 0.065 | 0 | 1.6 | 7 |
| Qwen3.8 Flash | 1.01 % | 93.2 % | 2.61 % | 3/3 | 0.057 | 492 | 13.6 | 0 |
| Claude Haiku 5.5 | 1.25 % | 94.0 % | 2.38 % | 3/3 | 0.053 | 323 | 5.3 | 0 |
| DeepSeek V4.1 Flash | 1.69 % | 93.8 % | 1.79 % | 3/3 | 0.053 | 838 | 10.0 | 0 |
| GPT-6 Luna | 1.77 % | 92.3 % | 2.62 % | 3/3 | 0.079 | 875 | 14.0 | 0 |
| Qwen3-VL-8B, local | 2.22 % | 92.6 % | 1.79 % | 3/3 | free | 0 | 4.5 | 0 |
Medians over the pages each model read. “Pages not read” are refusals; the pages Qwen3.8 Flash and DeepSeek V4.1 Flash were rate-limited on were read again one at a time in three further passes, so their rows are complete and their seconds per page include the slower passes. Seconds per page are wall time with four pages in flight for the cloud and one process at a time for the local model.
The table is sorted by the error rate on the German scans, the set with the most writers. The chart at the top plots that same error rate against the cents per page; an orange dot is a model that nothing else beats on both axes at once.
Three models are worth your money, four are not
Gemini 3.1 Flash-Lite is the cheapest of the seven at 0.046 cents a page, the fastest at under two seconds, and on every set either the best reader or within a third of a point of it: 0.54 % on the German scans, 95.0 % of the words on the photos, and 1.00 % on my tablet pages, where it was the best of the eight. Claude Haiku 5.5 costs the same, 0.053 cents, reads the scans at 1.25 % and the photos at 94.0 %, and is one of the two models, with GPT-6 Luna, that read all 264 pages at the first attempt. Gemini 4 Argon is the best reader of paper, 0.23 % on the scans and 95.6 % of the words on the photos, at 0.37 cents a page, eight times the Flash-Lite; on my tablet pages it did not beat the Flash-Lite, and its median there sits on one page it wrote in LaTeX.
Of the other four, Gemini 3.5 Flash-Lite costs 40 % more than 3.1 and reads no better on any set. GPT-6 Luna is the dearest of the cheap tier and the weakest reader on all three sets; its 875 thinking tokens a page are billed and did not help. Qwen3.8 Flash reads the scans well, at 1.01 %, but takes fourteen seconds a page, and Alibaba answered a seventh of the requests with “too many requests” even one page at a time. DeepSeek V4.1 Flash has the lowest list price of the seven and ends up costing exactly what Haiku costs, because it thinks for 838 tokens a page. It reads the scans worse than Haiku and my tablet pages better, and takes ten seconds a page. The table does not show how it got there. At the plugin’s four pages in flight the host refused 95 of the 264 requests as too many, and one page at a time it still refused four in ten, so the row is complete only after three further passes. The plugin sets such a page aside for a later sync, and a notebook would arrive a third unread the first time. It also ran on a third-party host at reduced precision, because DeepSeek’s own endpoint is closed to an OpenRouter account that forbids providers to train on its data, which mine does and yours should.
The list price is not the page price
Claude Haiku 5.5 and GPT-6 Luna have the same list price, $0.10 per million input tokens and $0.50 per million output. Measured per page, Luna costs half as much again, because it thinks for 875 tokens before it answers and Haiku for 323, and thinking is billed as output. Gemini 3.1 Flash-Lite lists at two and a half times Haiku’s input price and three times its output price, and still comes out cheaper per page: it does not think at all by default, and Google’s image tokenisation charges a page at about 1 200 tokens where Anthropic’s charges 2 700. DeepSeek V4.1 Flash has the lowest list price of the seven, less than half of Haiku’s, and the same page price, because it thinks for 838 tokens a page. Qwen3.8 Flash thinks for 492 and lands a shade above Haiku. And Gemini 4 Argon’s price, the dearest in the table, is promotional until 30 November 2026 and doubles afterwards.
Gemini refuses text it knows
On 7 of the 77 German pages Gemini 3.1 Flash-Lite answered with no text and the finish reason
RECITATION: the model recognised a published Wikipedia paragraph and would not reproduce it.
Gemini 3.5 Flash-Lite did the same on 6 of them, Gemini 4 Argon on 2, one of those as a content
filter, and each of the three also refused one of the 172 phone photos. No other provider refused
a page. In the table these count as pages not read, and the error rates of the three Gemini models
are over the pages they did read.
In version 1.8.4 such a page arrives as if it were blank. The provider answers with status 200 and an empty text, which is also what a legitimately empty page looks like, so the plugin writes no text and raises no error. You notice when you look for the words. Since version 1.8.5 the plugin leaves such a page out and says at the end of the sync that the model declined it. The page is still not read, though; only another model reads it. A reader who copies a poem, a quotation or a passage from a book by hand will meet this. A reader writing their own words will not: on my fifteen pages and on the 171 other photos it never happened.
Where the three sets agree
The three sets agree at the ends and argue in the middle. Gemini 4 Argon and Gemini 3.1 Flash-Lite are the two best readers of both paper sets, the 77 scans and the 172 photos, and GPT-6 Luna is the weakest cloud model on all three. Between them the order shifts with the set, and on my fifteen tablet pages it shifts with single pages: the medians there run from 1.0 % to 2.6 %, and a model moves a full place on the strength of one formula written in LaTeX or one margin note placed at the wrong end. Clean copied prose on a flat scan is the easiest thing any of these models read, under a percent for the top three. My pages are harder because I made them so, with a diagram, corrections and a margin note among the fifteen. The phone photos are hardest for everyone: the best model misses five words in a hundred, the worst eight.
So the ranking on tablet ink is one writer’s ranking, as promised, but the paper sets with their hundreds of hands put the same two models at the top and the same one at the bottom, and that is what the recommendation rests on. And in every row the bulleted list, the numbered list and the table on my pages came back as a list, a list and a table from all eight models, the local one included.
Where the local model stands
Everything above costs money and sends the page to somebody’s server. The plugin’s default on a Mac does neither: Apple’s built-in recognition, and, if you opt in, a model the plugin downloads and runs on your own machine (handwriting recognition on your own machine). The downloadable model is the one in the table’s last row, read with the same request on the same 264 pages. A second test put eight other models that run on a Mac against it: which local model reads handwriting best.
On paper it is last. The German scans come out at 2.22 %, against 1.77 % for the weakest cloud model and 0.54 % for Gemini 3.1 Flash-Lite; on the phone photos it finds 92.6 % of the labelled words, within half a point of GPT-6 Luna and two and a half points behind the Flash-Lite. Shadows, ruled paper and a photo taken at an angle cost it more than they cost the cloud. On my reMarkable pages, the condition the plugin actually sends, it reads at 1.79 %, which in this run is better than Claude Haiku 5.5, Gemini 4 Argon, Gemini 3.5 Flash-Lite, Qwen3.8 Flash and GPT-6 Luna, level with DeepSeek, and behind Gemini 3.1 Flash-Lite alone. Fifteen pages of one hand are not a ranking, but they are enough to say that on clean tablet ink the free model keeps the paid ones company. It refused no page, kept every list and table, and its bad pages are everyone’s bad pages: the diagram, the corrections, the margin note.
What you accept for keeping the page at home, in plain terms:
- You need a machine that can run it. The 8-billion model needs a Mac with Apple silicon and 16 GB of memory or more: 6.2 GB to download once, about 8 GB of memory while a page is read. A Mac with 8 GB gets a 2-billion model instead, 1.6 GB to download, which reads my fifteen pages at 6.6 % instead of 1.8 %, still a third of what Apple’s own recognition makes of them (19.1 %). Windows on Arm can run the download too. On Windows with an Intel or AMD chip, and on Linux, the plugin downloads nothing; you run Ollama or LM Studio yourself and point the plugin at it, with any vision model you like.
- It is slower. On the M5 Max this test ran on, the local model took 2.9 seconds per reMarkable page and 4.5 seconds per page over all 264; on the M2 Max the plugin’s published figure comes from, 8 seconds a page. Gemini 3.1 Flash-Lite took 1.8 seconds a page and Haiku 5.3, and the plugin sends four pages at once. A notebook of fifty pages is a coffee break on a laptop and under a minute in the cloud.
- It makes more errors on paper and none more that I could measure on ink: four times the errors of Gemini 3.1 Flash-Lite on the German scans, two and a half points fewer words found on the phone photos, and level with the cloud on my tablet pages.
- Nothing is read in the background while the laptop lid is shut, because your machine does the work, not a server.
In return the page never leaves your machine. It is drawn to a temporary file in your own temp directory, read there, and deleted. No account, no key, no bill, no page anywhere but your disk. For many readers that settles it before any table does, and the plugin is built so that it can. The cloud is the opt-in, part of Pro, on a key of your own.
What it costs
The whole test, seven cloud models over 264 pages each, 1 848 page reads plus the rate-limited retries, cost $1.90 on my OpenRouter account. $0.97 of that was Gemini 4 Argon alone; the other six together cost less than a dollar. The local model cost electricity.
For a month of your own notes the numbers look like this. The middle column is roughly my own volume, a few pages a day:
| per month | 100 pages | 250 pages | 500 pages |
|---|---|---|---|
| Gemini 3.1 Flash-Lite | 5 ¢ | 12 ¢ | 23 ¢ |
| Claude Haiku 5.5 | 5 ¢ | 13 ¢ | 27 ¢ |
| Gemini 4 Argon | 37 ¢ | 92 ¢ | $1.84 |
| Qwen3-VL-8B on your Mac | $0 | $0 | $0 |
For scale: reMarkable’s own handwriting search needs a Connect subscription at US$3.99 a month. A year of Haiku at 250 pages a month costs $1.59, a year of Gemini 3.1 Flash-Lite $1.38, each less than half of one month of Connect. The one-time price of Tagged Sync Pro, which the cloud backends are part of, is €24; the model bills you separately, through the key you give it.
What a Tagged Sync user should set
Gemini 3.1 Flash-Lite, unless you copy published text by hand. It is the cheapest model in the table, the fastest, the best reader of my tablet pages, and within a third of a point of the best reader of paper. If you copy poems, quotations or book passages, set Claude Haiku 5.5 instead, because Gemini refuses those pages and Haiku refused none. It costs the same per page, it read all 264 pages, and on the German scans it reads at about a point, which is one wrong character per line. On your own notes the difference between the two will be smaller than the difference between two of your own pages.
Gemini 4 Argon when the page is paper and every character counts. A scanned letter, an old notebook photographed page by page: Argon reads those at a quarter of a percent, half the errors of the Flash-Lite, for eight times the price, which at 250 pages a month is still under a dollar. On tablet ink it bought nothing I could measure, and its one bad tablet page was the formula page, which it wrote in LaTeX: correct, and not what was on the page.
The local model when the page must not leave the machine. It is the weakest reader of paper, and on tablet ink it is as good as most of the cloud. It is already the plugin’s opt-in on a Mac with Apple silicon.
To set it up, open Settings, Transcription, Backend. Choose Google Gemini with a key from
Google AI Studio and type gemini-3.1-flash-lite into the
Model field; or Anthropic (Claude) with a key from the Anthropic console
and claude-haiku-5-5. If you would rather hold one key for every provider, choose OpenRouter
and type the model as OpenRouter lists it: google/gemini-3.1-flash-lite,
anthropic/claude-haiku-5.5, google/gemini-4-argon. The model id is typed, not picked from a
list, on purpose: a model name shipped inside a plugin goes stale the day its provider retires it,
and the one you typed is the one you are billed for.
What this does not settle
- One run per model, one day. Providers change models under the same name; the nightly on the accuracy page keeps reading my fifteen pages, and a model that drifts will show there first.
- The tablet condition is one writer. The ranking on paper and the ranking on ink agree, which is the best I can offer until a multi-writer ink set exists.
- Every model ran at its provider’s default for thinking. A model switched to not thinking would be cheaper and might read differently; the plugin does not offer that switch today.
- Version 1.8.4 cannot tell a refused page from an empty one, so a Gemini recitation refusal arrives silently. Version 1.8.5 reports it.
- Marks a Bullet Journal writer relies on, a dot, a cross, an arrow at the start of a line, are not scored here; the prompt asks for Markdown structure, and a dot becomes a dash. That is a measurement for another day.
Sources and licences
The GNHK and ScaDS.AI pages shown here are reproduced under their CC BY 4.0 licences with attribution as above; the full sets are available from their publishers. My fifteen pages are in the plugin’s repository under its own licence.