# Pdfium Syntax Pages

> Use when accessing, counting, indexing, or iterating the pages of a PDF with pdfium-render, or reading a page's size or paper format. Prevents the page-access mistakes: storing a page index as u16 after the 0.9.0 c_int change, loading every page just to read its dimensions, calling pages() when a mutable collection is required, and assuming get() cannot fail. Covers PdfDocument::pages and pages_mut, the PdfPages collection (len, is_empty, first, last, get, iter), page_size and page_sizes for load-free dimensions, PdfPage::width, height and paper_size, the PdfPageIndex type, and iterating with enumerate. Keywords: pdfium-render, pages, PdfPages, PdfPage, page count, page index, PdfPageIndex, iter, enumerate, first, last, get, page_size, page_sizes, paper_size, PdfPagePaperSize, pages_mut, "how many pages", "loop over pages", "get page by number", "page out of bounds", "PageIndexOutOfBounds", "expected u16 found c_int", "how big is each page", "iterate PDF pages".

- Skill: `impertio-studio/pdfium-syntax-pages` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/pdfium-syntax-pages`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/pdfium-syntax-pages/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/pdfium-syntax-pages

---


# pdfium-render Pages

This skill covers the page layer of pdfium-render: reaching the page
collection from a `PdfDocument`, counting and indexing pages, iterating them,
and reading a page's size and paper format. Rendering a page is the scope of
pdfium-syntax-rendering; adding, deleting, and reordering pages is
pdfium-impl-page-manipulation and pdfium-impl-multi-page.

## Quick Reference: Page Access Flow

```text
PdfDocument
  .pages()      -> &PdfPages       immutable collection (read, iterate)
  .pages_mut()  -> &mut PdfPages   mutable collection (added 0.8.0)

PdfPages
  .len()        -> PdfPageIndex    page count
  .is_empty()   -> bool
  .get(index)   -> Result<PdfPage, PdfiumError>
  .first()      -> Result<PdfPage, PdfiumError>
  .last()       -> Result<PdfPage, PdfiumError>
  .iter()       -> PdfPagesIterator   yields PdfPage in order
  .page_size(i) -> Result<PdfRect, PdfiumError>     no page load
  .page_sizes() -> Result<Vec<PdfRect>, PdfiumError> no page load

PdfPage
  .width()      -> PdfPoints
  .height()     -> PdfPoints
  .paper_size() -> PdfPagePaperSize
```

ALWAYS reach a page through `pages()` or `pages_mut()` on the owning
`PdfDocument`. NEVER assume a page can be constructed standalone; a `PdfPage`
borrows from its `PdfDocument` (see pdfium-core-architecture).

## 1. Reaching the Page Collection

`PdfDocument` exposes two collection accessors:

- `pages()` returns `&PdfPages<'a>` for reading and iterating.
- `pages_mut()` returns `&mut PdfPages<'a>` for mutation (creating, importing,
  deleting, reordering pages). It was **added in 0.8.0**.

ALWAYS use `pages_mut()` when the operation changes the page set. NEVER try to
mutate the page set through `pages()`; the immutable collection has no
creation or import functions, and the borrow checker rejects the attempt.

## 2. The PdfPages Collection

`PdfPages` is the collection of all pages in a document. It is generic over
the document lifetime `'a`.

### Counting

```rust
pub fn len(&self) -> PdfPageIndex
pub fn is_empty(&self) -> bool
```

`len()` returns a `PdfPageIndex`, not a plain `usize`. ALWAYS check
`is_empty()` (or `len()`) before calling `first()` or `last()` on a document
that could be empty.

### Single-page access

```rust
pub fn get(&self, index: PdfPageIndex) -> Result<PdfPage<'a>, PdfiumError>
pub fn first(&self) -> Result<PdfPage<'a>, PdfiumError>
pub fn last(&self) -> Result<PdfPage<'a>, PdfiumError>
```

All three return a `Result`. Pages are **0-indexed**: the first page is index
`0`, the last is `len() - 1`. An out-of-range index returns
`Err(PdfiumError::PageIndexOutOfBounds)`. `first()` and `last()` on an empty
document return an error.

ALWAYS treat `get()`, `first()`, and `last()` as fallible and handle the
`Result`. NEVER unwrap a page lookup on a document whose page count is
unknown.

### Iterating

```rust
pub fn iter(&self) -> PdfPagesIterator<'_>
```

`iter()` yields every `PdfPage` in document order. Pair it with `enumerate()`
to get a 0-based page number alongside each page:

```rust
for (index, page) in document.pages().iter().enumerate() {
    println!("page {}: {} pt wide", index, page.width().value);
}
```

ALWAYS use `iter().enumerate()` when a page number is needed during a loop.

## 3. Page Sizes Without Loading the Page

Loading a `PdfPage` parses its content. When only the dimensions are needed,
`PdfPages` provides load-free size queries that are considerably faster:

```rust
pub fn page_size(&self, index: PdfPageIndex) -> Result<PdfRect, PdfiumError>
pub fn page_sizes(&self) -> Result<Vec<PdfRect>, PdfiumError>
```

`page_size()` returns the size of one page as a `PdfRect` (measured in
`PdfPoints`) without loading it. `page_sizes()` returns the sizes of every
page in one call.

ALWAYS use `page_size()` or `page_sizes()` when the task only needs
dimensions. NEVER call `get()` and then `width()`/`height()` purely to read a
size; that loads the whole page and is slower.

Version note: the docs.rs 0.9.x API names these `page_size` and `page_sizes`.
The 0.9.0 cleanup release removed `get_`-prefixed accessors across the crate;
do not use a `get_page_size` form on the 0.9.x line.

## 4. PdfPage Basics: Size and Paper Format

```rust
pub fn width(&self) -> PdfPoints
pub fn height(&self) -> PdfPoints
pub fn paper_size(&self) -> PdfPagePaperSize
```

`width()` and `height()` return `PdfPoints`, the device-independent 1/72 inch
unit, **not** pixels. A US Letter page is `612.0 x 792.0` points. Converting
to pixels or physical units is the scope of pdfium-core-coordinates.

`paper_size()` returns a `PdfPagePaperSize`, an enum with three variants:

- `Portrait` : a known standard size in portrait orientation.
- `Landscape` : a known standard size in landscape orientation.
- `Custom` : a non-standard size, carried as a `(width, height)` pair in
  `PdfPoints`.

NEVER expect `PdfPagePaperSize` to be a flat list of `A4` / `Letter`
variants. It is orientation plus a known-or-custom size. Standard sizes are
reached through constructors and shortcuts such as `a4()` and `a3()`; see
references/methods.md.

## 5. Page Indexing and PdfPageIndex

`PdfPageIndex` is the index and count type for pages:

```rust
pub type PdfPageIndex = c_int;
```

Version trap: in **0.9.0** `PdfPageIndex` changed from `u16` to `c_int`. Code
written against 0.8.x that stores a page index or count as `u16` fails to
compile against 0.9.x with a type-mismatch error.

ALWAYS store a page index or page count as `PdfPageIndex` (or let type
inference carry the value), so the code survives the 0.8.x to 0.9.x upgrade.
NEVER hardcode the underlying integer type (`u16` or `c_int`) for a page
index; use the `PdfPageIndex` alias.

## 6. Iterating for Page Numbers

The canonical render-every-page loop pairs `iter()` with `enumerate()`:

```rust
let document = pdfium.load_pdf_from_file("input.pdf", None)?;
for (index, page) in document.pages().iter().enumerate() {
    // `index` is the 0-based page number, `page` is the PdfPage.
    println!("page {index}: {:.0} x {:.0} pt",
        page.width().value, page.height().value);
}
```

`enumerate()` yields a `usize` index. Use it directly for display or
filenames. When the index must feed back into `get()` or `page_size()`,
convert it to `PdfPageIndex`.

## Decision Tree: Which Page Accessor

```text
What do I need from the pages?

  Just the count
    -> pages().len()  /  is_empty()

  One specific page, index known
    -> pages().get(index)   (handle the Result)

  The first or last page
    -> pages().first()  /  pages().last()   (handle the Result)

  Walk every page in order
    -> pages().iter()   (add .enumerate() for page numbers)

  Only the size of a page, content not needed
    -> pages().page_size(index)  /  pages().page_sizes()

  Change the set of pages (add / delete / import / reorder)
    -> pages_mut()   then see pdfium-impl-page-manipulation
```

## ALWAYS / NEVER

- ALWAYS reach pages via `pages()` or `pages_mut()` on the `PdfDocument`.
- ALWAYS use `pages_mut()` for any operation that changes the page set.
- ALWAYS treat `get()`, `first()`, and `last()` as fallible; pages are
  0-indexed and an out-of-range index returns `PageIndexOutOfBounds`.
- ALWAYS use `page_size()` / `page_sizes()` when only dimensions are needed.
- ALWAYS store a page index or count as `PdfPageIndex`.
- ALWAYS use `iter().enumerate()` to pair pages with page numbers.
- NEVER store a page index as `u16`; `PdfPageIndex` is `c_int` since 0.9.0.
- NEVER load a page with `get()` just to read its size.
- NEVER call `first()` / `last()` without an `is_empty()` guard on a document
  that could have zero pages.
- NEVER treat `width()` / `height()` as pixel counts; they are `PdfPoints`.

## Cross-References

- **pdfium-core-coordinates** : `PdfPoints`, converting page sizes to pixels
  or physical units.
- **pdfium-syntax-rendering** : turning a `PdfPage` into a `PdfBitmap`.
- **pdfium-impl-page-manipulation** : creating, deleting, rotating, and
  cropping pages through `pages_mut()`.
- **pdfium-impl-multi-page** : importing and merging pages across documents.
- **pdfium-core-architecture** : where `PdfPages` and `PdfPage` sit in the
  ownership tree.

## Reference Files

- `references/methods.md` : signatures of `PdfDocument` page accessors, the
  `PdfPages` collection, `PdfPage` basics, `PdfPageIndex`, and
  `PdfPagePaperSize`, with version annotations.
- `references/examples.md` : verified Rust code for counting, indexing,
  iterating, and reading sizes.
- `references/anti-patterns.md` : real page-access failures with the cause
  and the fix.

## Sources

API names and signatures verified on 2026-05-20 via WebFetch against the
package `SOURCES.md`:

- `https://docs.rs/pdfium-render/latest/pdfium_render/prelude/struct.PdfPages.html`
- `https://docs.rs/pdfium-render/latest/pdfium_render/prelude/struct.PdfPage.html`
- `https://docs.rs/pdfium-render/latest/pdfium_render/prelude/struct.PdfDocument.html`
- `https://docs.rs/pdfium-render/latest/pdfium_render/prelude/type.PdfPageIndex.html`
- `https://docs.rs/pdfium-render/latest/pdfium_render/prelude/enum.PdfPagePaperSize.html`
- `https://github.com/ajrcarey/pdfium-render` (README, version history).

