---
title: "Getting started with OneOcr"
url: https://recursiveai.org/oneocr/docs/getting-started/
description: "Install OneOcr for .NET 10, read the text of an invoice image, walk the page model with its boxes and confidences, turn the page into Markdown, and set a…"
version: "1.0.0"
---

# Getting started with OneOcr

Install OneOcr for .NET 10, read the text of an invoice image, walk the page model with its boxes and confidences, turn the page into Markdown, and set a default engine. No native binaries, no `tessdata`, no network.

## Install

OneOcr targets `net10.0`, so you need the .NET 10 SDK. Every package shares one version; this guide uses 1.0.0.

```shell
dotnet new console -o OneOcrStart
cd OneOcrStart
dotnet add package RecursiveAI.OneOcr --version 1.0.0
```

`RecursiveAI.OneOcr` brings in `RecursiveAI.OneOcr.Models`, which embeds the recognizer, the page detector and the two word models and checks them against their SHA-256 pins on every load. There is nothing to download and no model path to set. Pixels come from [OneImage](https://recursiveai.org/oneimage/), so any `OneImage.Image` (PNG, JPEG, WebP, TIFF and so on) is an input. The same weights are also attached to the [v1.0.0 release on GitHub](https://github.com/recursive-ai-oss/oneocr-csharp/releases/tag/v1.0.0) for `OcrEngine.Load(path)` and `.WithDetector(path)`.

## The sample images

The guide and the [cookbook](https://recursiveai.org/oneocr/cookbook/) read two images. `invoice.png` is a one-page A4 invoice rendered from HTML at 300 DPI (2481 × 3509 pixels), with a seller and buyer block, a table of items and totals. `receipt.png` is a till receipt rendered at twice screen resolution (920 × 940). Any PNG or JPEG of a flat document works the same way; the outputs below are what 1.0.0 printed for these two.

## Read the text

`OcrEngine.LoadBundled()` loads the bundled models. An engine is immutable and thread-safe: load it once and share it. `ToText` returns the page in reading order, with lines separated by a newline and table cells by a tab:

```csharp
using OneImage;
using OneOcr;

OcrEngine engine = OcrEngine.LoadBundled();      // once at startup; immutable and thread-safe

Image image = Image.Load("invoice.png");
Console.WriteLine(image.ToText(engine));
```

```text
Northwind Supply Ltd
14 Harbour Street
BS1 4DJ Bristol
United Kingdom
VAT ID: GB284193752
INVOICE
Bill to
Blue Heron Bakery
88 Elm Road
OX1 2JD Oxford
United Kingdom
Invoice no.
INV-2041
Date
Due date
Order no.
14/10/2026
13/11/2026
PO-7731
Description	Qty	Unit price	VAT	Amount
Flour, 25 kg bag	4 pcs	31.50	0%	126.00
Cane sugar, 10 kg	2 pcs	18.25	0%	36.50
Baking parchment roll	6 pcs	7.40	20%	44.40
Payment terms: Payable within 30 days
Subtotal
VAT total
Total
£206.90
£8.88
£215.78
IBAN: GB33 BUKB 2020 1555 5555 55	BIC: BUKBGB22	Tel. +44 117 496 0321
```

The page detector found the table and the blocks; reading order goes block by block, so the labels of the meta grid and the totals come before their values.

## The page model

`Ocr` runs the same pipeline and returns the whole `OcrPage`: blocks, lines, words and characters with boxes, tables, key–value pairs and diagnostics. Coordinates are pixels from the top left, y down. A word’s `Confidence` is the calibrated probability that it is exactly right:

```csharp
using OneImage;
using OneOcr;

OcrEngine engine = OcrEngine.LoadBundled();
OcrPage page = Image.Load("invoice.png").Ocr(engine);

Console.WriteLine($"{page.Width} x {page.Height}, {page.Blocks.Count} blocks, {page.Words.Count} words, {page.Tables.Count} table");
foreach (OcrWord word in page.Blocks[0].Lines[0].Words)
    Console.WriteLine($"{word.Text,-10} {word.Confidence:F3}  ({word.Box.Left:F0}, {word.Box.Top:F0}) to ({word.Box.Right:F0}, {word.Box.Bottom:F0})");
foreach (OcrDiagnostic diagnostic in page.Diagnostics)
    Console.WriteLine($"{diagnostic.Code}: {diagnostic.Message}");
```

```text
2481 x 3509, 19 blocks, 98 words, 1 table
Northwind  0.986  (231, 198) to (580, 247)
Supply     1.000  (614, 198) to (845, 260)
Ltd        0.974  (878, 200) to (963, 247)
OCR101: UnitsPerInch is estimated at 200 from the size of the text; pass OcrOptions.Dpi to set it.
OCR107: 1 word(s) read from specks, grain or stray marks were dropped as noise; pass OcrOptions.DropNoise = false to keep them.
```

Diagnostics say what the reader decided on its own. This PNG doesn’t declare a resolution, so `OCR101` says it was estimated; pass `new OcrOptions { Dpi = 300 }` when you know it. It only sets `UnitsPerInch`: recognition doesn’t depend on it.

## Markdown

`ToMarkdown` builds Markdown from the page model with no model call: headings from text size, lists, and pipe tables from detected tables, with headers, footers and page numbers dropped.

```csharp
using OneImage;
using OneOcr;

OcrEngine engine = OcrEngine.LoadBundled();
Console.WriteLine(Image.Load("invoice.png").ToMarkdown(engine));
```

```text
Northwind Supply Ltd 14 Harbour Street BS1 4DJ Bristol United Kingdom VAT ID: GB284193752

# INVOICE

## Bill to

Blue Heron Bakery 88 Elm Road

OX1 2JD Oxford United Kingdom

Invoice no.

INV-2041

Date

Due date

Order no.

14/10/2026

13/11/2026 PO-7731

| Description | Qty | Unit price | VAT | Amount |
| --- | --- | --- | --- | --- |
| Flour, 25 kg bag | 4 pcs | 31.50 | 0% | 126.00 |
| Cane sugar, 10 kg | 2 pcs | 18.25 | 0% | 36.50 |
| Baking parchment roll | 6 pcs | 7.40 | 20% | 44.40 |

Payment terms: Payable within 30 days

Subtotal

VAT total

Total

£206.90

£8.88

£215.78

IBAN: GB33 BUKB 2020 1555 5555 55 BIC: BUKBGB22 Tel. +44 117 496 0321
```

## A default engine

If you’d rather not pass the engine around, set a process-wide default once. The extension methods without an engine argument then use it; until you call `ConfigureDefault`, `OcrEngine.Default` throws `InvalidOperationException`.

```csharp
using OneImage;
using OneOcr;

OcrEngine.ConfigureDefault();                    // the bundled models become OcrEngine.Default
Console.WriteLine($"Kernels: {OcrEngine.Default.KernelPath}");

string text = Image.Load("receipt.png").ToText();   // no engine argument: the default is used
Console.WriteLine(text);
```

```text
Kernels: Avx512
Corner Market
1402 Oak Street
78704 Austin
+1 512 555 0142
Date: 24/10/2026
Time: 14:32
Coffee beans	12.99
2x Oat milk	8.98
Bagels	5.25
Subtotal	27.22
Tax 8.25 %	2.07
TOTAL	$ 29.29
Paid by	Card **** 4821
Thank you!
```

`KernelPath` says which kernels run: `Avx512`, `Avx2`, `Vector128` or `Scalar`. The text, boxes and confidences are the same on all four ([Same bytes on every machine](https://recursiveai.org/oneocr/cookbook/same-bytes-everywhere/)).

## Good to know

- Every local call takes a `CancellationToken` and has an `Async` twin (`OcrAsync`, `ToTextAsync`, `ToMarkdownAsync`) that returns the same result.
- `Ocr(Image)` reads one page and throws `ArgumentException` for an image with several frames; `OcrPages` reads every frame of a TIFF.
- Errors are typed: `OcrFormatException` for bytes that aren’t what they claim to be, `OcrLimitException` when an `OcrLimits` bound is crossed (checked before anything large is allocated), `OcrModelException` for a bad model file.
- Scripts: Latin (including the EU languages, Turkish and Vietnamese), Greek and Cyrillic in one recognizer. CJK, Arabic and Indic scripts, handwriting and scene text are not supported yet.

## Next

- [Invoices as fields](https://recursiveai.org/oneocr/cookbook/invoices/): typed fields with EN 16931 ids, each with the words and box it was read from.
- [Words to check](https://recursiveai.org/oneocr/cookbook/words-to-check/): use calibrated confidence to find what a person should look at.
- [PDF pages](https://recursiveai.org/oneocr/cookbook/pdf-pages/): text-layer words and OCR of scanned regions in one page model.
- [Moving from Tesseract](https://recursiveai.org/oneocr/docs/migrating-from-tesseract/): commands, modes and outputs side by side.
- [Overview and benchmarks](https://recursiveai.org/oneocr/docs/overview/#benchmarks): the README, with results against Tesseract, PaddleOCR, docTR and Apple Vision.
