---
title: "PDF pages"
url: https://recursiveai.org/oneocr/cookbook/pdf-pages/
description: "Read a PDF whose page has both real text and a scanned image: the text layer is used where it exists, the image is read with OCR, and every word says which."
version: "1.0.0"
---

# PDF pages

Read a PDF whose page has both real text and a scanned image: the text layer is used where it exists, the image is read with OCR, and every word says which.

```shell
dotnet add package RecursiveAI.OneOcr --version 1.0.0
dotnet add package RecursiveAI.OneOcr.Pdf --version 1.0.0
```

`expense.pdf` is a one-page US Letter PDF printed from HTML: a heading and a paragraph as text, and the [grainy receipt](https://recursiveai.org/oneocr/cookbook/words-to-check/) as an embedded image.

```csharp
using OneOcr;
using OneOcr.Pdf;

OcrEngine engine = OcrEngine.LoadBundled();
IReadOnlyList<OcrPage> pages = PdfOcr.Read("expense.pdf", engine);

foreach (OcrPage page in pages)
{
    Console.WriteLine($"page {page.Index + 1}: {page.Width:F0} x {page.Height:F0} pt, {page.Words.Count} words");
    foreach (var group in page.Words.GroupBy(w => w.Source))
        Console.WriteLine($"  {group.Key}: {string.Join(" ", group.Take(8).Select(w => w.Text))} ...");
    foreach (OcrDiagnostic diagnostic in page.Diagnostics)
        Console.WriteLine($"  {diagnostic.Code}: {diagnostic.Message}");
}
```

```text
page 1: 612 x 792 pt, 64 words
  TextLayer: Expense report EX-118 Submitted by Dana Whitfield on ...
  Ocr: Corner Market 1402 Oak Street 78704 Austin +1 ...
  OCR301: 1 regions were read from pixels at 300 DPI (47 words).
```

- Each PDF page is one `OcrPage` in PDF points, y down; `ToPdf` maps coordinates back to PDF user space.
- Image regions the text doesn’t cover are rendered at `PdfOcrOptions.RenderDpi` (300 by default) through OneImage.Pdf and read with the local engine; `OCR301` says how many.
- A text layer isn’t trusted blindly: an invisible layer over a scan (an earlier OCR pass) is read again unless you set `TrustExistingOcrLayer`, and garbled lines are read again from a render. See [PDF pages](https://recursiveai.org/oneocr/docs/pdf-bridge/).
- For a `PdfPage` or `PdfDocument` you already hold from [OnePDF](https://recursiveai.org/onepdf/), the extension methods `Ocr`, `ToText`, `ToMarkdown`, `ExtractInvoice` and `ExtractReceipt` do the same. Text drawn as outlined glyphs and annotations aren’t read yet.
