# What changed in fpdf2

> 41 changes in fpdf2 2 from its official release notes, upgrade guides and advisories: 3 breaking, 7 new APIs and options. Each one cited. Sources checked 2026-10-20. HTML: https://unstale.sh/pypi/fpdf2/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## fpdf2 2

### Breaking changes

- Booleans in arrays and dictionaries serialize as lowercase true and false, None in arrays as null, and filtering empty dictionary fields preserves False and numeric zero. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- A custom height passed in a text region is now applied to the line it terminates, rather than the first line of the following paragraph. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Rejects SVG <use> cycles and excessive nested expansion to prevent resource exhaustion in FPDF.image(). (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)

### New APIs and options

- Adds an align parameter to control horizontal alignment of page-number substitution text inside reserved alias space. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Adds an appearance parameter accepting FileAttachmentAppearance.HIDDEN to hide the annotation's default icon while keeping the embedded file reachable. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Adds support for page number alias substitution with bidirectional and RTL text shaping. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Adds configurable SVG complexity limits when rendering SVG images. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Adds support for keeping aspect ratio for images in templates. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Adds basic support for SVG <switch> elements in the SVG parser. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Adds basic support for SVG <symbol> elements in the SVG parser. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)

### Behavior and default changes

- Fonts with both outline and bitmap glyphs now prefer outline glyphs. (2.8.7) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.7)

### Fixes and other changes

- PDF/A-1 documents using TrueType or CFF-based CID fonts now include a /CIDSet stream in each font descriptor, as required by ISO 19005-1. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Escaped Markdown markers adjacent to emphasis markers in link labels no longer lose literal characters or apply unintended styling. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- List bullets now use correct font styling instead of inheriting styles from a preceding heading. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- List line-height values that are not bare numbers are ignored, using the default line height instead of raising IndexError. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Now accepts 1-element sequences per CSS shorthand rules and preserves existing Padding instances without redundant allocations. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Fixes table cells landing in the wrong column when a row is covered by several rowspans that do not start in column order. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Percentage width and height values with surrounding whitespace no longer raise ValueError. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Fixes a visual gap in subsequent text rendering after a page alias when text shaping is enabled. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- CMap mappings are split into blocks of at most 100 entries to meet the PDF specification. (2.8.9) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.9)
- Preserves boundary-neutral formatting during bidirectional text preprocessing. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Embeds CID-keyed CFF fonts as raw CFF programs so browser PDF viewers render them correctly. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Fixes the number of surviving escape characters. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Fixes text rendering when the first text on a page starts with a fallback glyph. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Dry runs now preserve link annotations and markdown formatting; ToC dry runs also preserve page order. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Can restore current_font when the selected font state has diverged. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Preserves consecutive markdown links without intervening spaces and supports markdown styling around links. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Treats RuntimeError like ImportError for the optional numpy import, so unsupported CPUs make numpy unavailable instead of causing import fpdf to fail. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Declares the default base state and display order so PDF viewers can list layers correctly. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Leading spaces on new lines inside preformatted blocks are no longer dropped. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Fixes rendering SVG arcs with very small sweeps that previously rounded to zero. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Counts SVG <switch> elements toward SVG complexity limits. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Font state no longer leaks onto the FPDF instance after text_columns() or text_region() exits, so subsequent cell() or write() calls use the caller's font. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Font state no longer leaks onto the FPDF instance after text_region() exits, so subsequent cell() or write() calls use the caller's font. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Avoids a spurious horizontal-space error when unbreakable text is split into many small fragments, such as by alternating fallback and main fonts. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Resets graphics state for ToC rendering and fixes page order after multi_cell dry runs in a ToC. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Fixes transform application on user space gradients. (2.8.8) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.8)
- Fixed the types for FPDF.add_font(). (2.8.7) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.7)
- Fixed the types for FPDF.output(). (2.8.7) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.7)
- Fixed the type for FPDF.title. (2.8.7) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.7)
- Reverted changes to ImageInfo that impacted the user-facing API. (2.8.7) — [release notes](https://github.com/py-pdf/fpdf2/releases/tag/2.8.7)
