NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #862 most downloaded on PyPI
Simple & fast PDF generation for Python
Last release 5 days ago
29 Sep 2026
Ships fairly regularly
a new release about every 3 months
Nearly every release is documented
notes for 49 of 49 stable releases
1 version withdrawn
withdrawn after publishing
9 years old
54 releases · first in 2017
align parameter for `FPDF.alias_nb_pages()` to control horizontal alignment (Align.L, Align.C, Align.R) of substitution text inside reserved alias spa
align parameter for FPDF.alias_nb_pages() to control horizontal alignment (Align.L, Align.C, Align.R) of substitution text inside reserved alias space - cf. issue #1926 - thanks to @prateek-dagarappearance parameter for FPDF.file_attachment_annotation(), accepting FileAttachmentAppearance.HIDDEN to give the annotation an empty appearance stream so its default icon is not displayed while the file stays embedded and reachable - cf. issue #561 - thanks to @ChrisJr404true and false, including in mixed numeric/boolean arrays; None in arrays is serialized as null; and filtering empty dictionary fields preserves False and numeric zero values - thanks to @agustin18width and height values with surrounding whitespace (e.g. width="100% ") no longer raise ValueError - thanks to @Anai-Guo/CIDSet stream in each font descriptor, as required by ISO 19005-1 (veraPDF rule 6.3.5-3) - cf. issue #88/ToUnicode and /Encoding CMap mappings into blocks of at most 100 entries, as required by the PDF specification - cf. issue #1952{nb} page alias when text shaping is enabled - cf. issue #1090 - thanks to @prateek-dagarFPDF.write_html() no longer raises IndexError: pop from empty list when a <ul> or <ol> element carries a line-height that is not a bare number (e.g. line-height: normal or line-height: 1.5em); such values are now ignored, and the default line height is used, consistently with <p line-height="x"> - thanks to @Anai-GuoFPDF.write_html() now renders list bullets with correct font styling instead of inheriting preceding heading (e.g. <h1>) styles - cf. issue #1921 - thanks to @prateek-dagarPadding.new() now accepts 1-element sequences per CSS shorthand rules and preserves existing Padding instances without redundant allocations_tt_font_widths to reuse _cid_font_widths glyph interval compression logic - thanks to @agustin18One column per quarter.
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation .
Source distribution for fpdf2 2.8.9 File Size Uploaded
fpdf2-2.8.9.tar.gz 380.9 kB Sep 29, 2026 Details
Table of built distributions (wheels) for fpdf2 2.8.9 File Interpreter ABI Platform Reset
fpdf2-2.8.9-py3-none-any.whl 341.3 kB Sep 29, 2026 Python 3 none any Details
Total release size: 722.1 kB
> Upgrading to fpdf2 2.8.8 is strongly recommended for applications that render user-provided images, SVGs, or HTML content.
[!WARNING] Upgrading to fpdf2 2.8.8 is strongly recommended for applications that render user-provided images, SVGs, or HTML content.
FPDF.svg_limits and SVGLimits to configure SVG complexity limits while rendering SVG imagesresource_access_policy and Security considerations documentationFPDF.optional_content() context manager to mark content as visible on screen only or in print only, using PDF Optional Content Groups - cf. issue #441, based on a recipe by @digidigital - thanks to @eugen-goebel<symbol> elements in the SVG parser - thanks to @Theo1335<switch> elements in the SVG parser - cf. issue #537 - thanks to @dannymaazParagraph.ln() in a text region is now applied to the line it terminates instead of the first line of the following paragraph - cf. issue #1786 - thanks to @Sanjays2402numpy import in image_parsing.py no longer crashes on CPUs unsupported by numpy's manylinux wheel baseline; RuntimeError is now treated the same as ImportError, so numpy degrades to unavailable instead of taking down import fpdf - cf. issue #1908 - thanks to @stumpylogFPDF instance after a text_columns() / text_region() context exits, so a subsequent pdf.cell() / pdf.write() renders at the caller's font instead of the last paragraph's - cf. issue #1804 - thanks to @Pawansingh3889FPDF.multi_cell - cf. issue #1807 - thanks to @CoLa5FPDF.multi_cell in dry-run - cf. issue #1840 - thanks to @CoLa5FPDF.multi_cell in ToC - cf. issue #1836 - thanks to @CoLa5<pre> and <pre><code> blocks are no longer dropped - cf. issue #1063 - thanks to @eugen-goebelFPDF.set_font() can restore current_font when the selected font state diverged - cf. PR #1872 - thanks to @gaoflow<use> cycles and excessive nested expansion to prevent resource exhaustion in FPDF.image()<switch> elements in SVG complexity limitsFor a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation .
Source distribution for fpdf2 2.8.8 File Size Uploaded
fpdf2-2.8.8.tar.gz 374.7 kB Aug 9, 2026 Details
Table of built distributions (wheels) for fpdf2 2.8.8 File Interpreter ABI Platform Reset
fpdf2-2.8.8-py3-none-any.whl 337.0 kB Aug 9, 2026 Python 3 none any Details
Total release size: 711.7 kB
types on FPDF.title, FPDF.add_font() and FPDF.output()
FPDF.title, FPDF.add_font() and FPDF.output()ImageInfo that impacted user-facing APIsupport for FPDF.transform() context manager to apply geometric transformations (translation, rotation, scaling, skewing) to the current graphics stat
FPDF.transform() context manager to apply geometric transformations (translation, rotation, scaling, skewing) to the current graphics state - thanks to @RaphaelFLT<linearGradient> and <radialGradient> elements - cf. issue #1580 - thanks to @Ani07-05collection_font_number in add_font()A5 value that could be specified as page format to the FPDF constructor was slightly incorrect, and the corresponding page dimensions have been fixed. This could lead to a minor change in your documents dimensions if you used this A5 page format. - cf. issue #1699INTERNAL layout, that caused an extra border to be rendered due to an erroneous use of list.index() - cf. issue #1669GraphicsState dataclass dataclass for clearer usage and stronger typingrotation(), skew(), and mirror() now delegate to transform() for standardized transform applicationthe deprecated uni parameter from fpdf.add_font()
fpdf2 with Bottle, CherryPy & Plone: link to documentation - thanks to @tanmayc07 and @Vidushi2709currentColor color value - cf. PR #1531 - thanks to @dlespiauunicode_range parameter for add_font() to restrict which unicode characters a font covers - cf. issue #1586 - thanks to @Malay-devvariations parameter added in add_font() to allow the use of variable fonts - cf. issue #1544: link to documentation - thanks to @Rapteonpalette parameter in add_font(), allowing users to choose alternate color palettes from color fonts (COLR/CPAL) and enabling different color schemes without embedding the font multiple times - cf. issue #1578, PR #1621 : link to documentationfvar to keep compatibility with variable fonts - cf. issue #1528libtiff detection logic to maintain compatibility with pillow v12.uni parameter from fpdf.add_font()dest parameter from fpdf.output()documentation on internal linking with variable page numbers
arc() method to document x and y arguments (#1473)numpy an optional dependency to improve the performance of pack_codes_into_bytes() - cf. issue #1380FPDF.write_html(): Fixed custom styling of <p> & tables - issue #1453IndexError was raised in some cases when rendering HTML with nested lists - cf. issue #1358IndexError was raised in some cases when using text_columns() with text shaping enabled - cf. issue #1439FPDF.offset_rendering() or FPDF.unbreakable() with large fonts - cf. issue #1444BT/ET contexts when using underline or strikethrough text - cf. issue #1456multi_cell() text clipping bug - issue #1471<a> tags in SVGs are now correctly rendered - cf. PR #1522accept_page_break is now only called once per page break - cf. issue #1489support for Output Intents on document level - thanks to @lka
v_align at the row level in tablesreset_page_indices parameter for insert_toc_placeholder()first_line_indent in text_region.Paragraphfpdf2 internals.notdef glyph - issue #1161 - thanks to @spacegaoriFPDF.write_html(): Fixed rendering of content following <a> tags; now correctly resets emphasis style post </a> tag: hyperlink styling contained within the tag authority. - issue #1311FPDF.table(): Fixed heading styles containing underline failing to render.FPDF.ln(): the method now allows a value of 0 to be provided for h.set_font() or add_page() but not actually used in the document are no longer included in the final output. This reduces file size and improves performance, especially for documents with many fallback fonts. - issue #1382KeyError was raised in some specific cases when auto-downscaling images - issue #1409v_align at the row level in tablesreset_page_indices parameter for insert_toc_placeholder()first_line_indent in text_region.Paragraphfpdf2 internals.notdef glyph - issue #1161 - thanks to @spacegaoriTableBordersLayout is now a non-enum class that supports customizable layouts. The members of the old enum class are now static members of the class and thus can be used as standard options using the same syntax as previously - cf. PR #957FPDF.write_html(): Fixed rendering of content following <a> tags; now correctly resets emphasis style post </a> tag: hyperlink styling contained within the tag authority. - issue #1311FPDF.table(): Fixed heading styles containing underline failing to render.FPDF.ln(): the method now allows a value of 0 to be provided for h.set_font() or add_page() but not actually used in the document are no longer included in the final output. This reduces file size and improves performance, especially for documents with many fallback fonts. - issue #1382KeyError was raised in some specific cases when auto-downscaling images - issue #1409new optional parameter border for table cells: users can define specific borders (left, right, top, bottom) for individual cells - thanks to @Kaustbh
border for table cells: users can define specific borders (left, right, top, bottom) for individual cells - thanks to @Kaustbh - issue #1192FPDF.write_html(): now parses <title> tags to set the document title. By default, it is added as PDF metadata, but not rendered in the document body. However, this can be enabled by passing render_title_tag=True to FPDF.write_html().Align values (along with string values like 'C', 'L', 'R') in l_margin of TextStyle to horizontally align text - issue #1282align= in FPDF.table(). Due to this correction, tables are now properly horizontally aligned on the page by default. This was always specified in the documentation, but was not in effect until now. You can revert to have left-aligned tables by passing align="LEFT" to FPDF.table().FPDF.set_text_shaping(False) was broken since version 2.7.8 and is now working properly - issue #1287rowspan, colspan > 1 and null text were not displayed properly - issue #1293CreationDate metadata used a wrong timezone offset for UTC - issue #1261insert_toc_placeholder() did not properly the page orientation, which caused a bug when the last page of the document was in a different orientation - issue #1213AnnotationDict properties can now be passed to FPDF.text_annotation(), FPDF.free_text_annotation(), FPDF.add_action(), FPDF.add_text_markup_annotation() & FPDF.ink_annotation(). This includes title, color, border_width...2.8.1, fpdf2 does not support Python 3.7, that reached end-of-life in 2023Note: a temporary 2.8.0 version was released but then erroneously removed on Pypi. Versions 2.8.0 & 2.8.1 are exactly the same.
Note: a temporary 2.8.0 version was released but then erroneously removed on Pypi. Versions 2.8.0 & 2.8.1 are exactly the same.
FPDF.bezier() - thanks to @awmc000Templates can now be also defined in JSON files.wrapmode in templates (default "WORD" can optionally be set to "CHAR" to support wrapping on characters for scripts like Chinese or Japanese) - cf. #1159 - thanks to @carlhiggsfpdf2 with Rough.js: link to docsfpdf2 with gunicorn: link to docsFPDF.image(): now handles keep_aspect_ratio in combination with an enum value provided to xFPDF.write_html(): now supports CSS page breaks properties : documentationFPDF.write_html(): new optional font_family parameter to set the default font familyFPDF.write_html(): spacing before lists can now be adjusted via the tag_styles attribute - thanks to @lcgeneralprojectsfpdf2 fails to parse a SVG imageFPDF.local_context() used to leak styling during page breaks, when rendering footer() & header() - MR: #1207fpdf.drawing.DeviceCMYK objects can now be passed to FPDF.set_draw_color(), FPDF.set_fill_color() and FPDF.set_text_color() without raising a ValueError: documentation.FPDF.write_html(): fixing rendering of <hr> tags, that do not trigger a page break anymoreFPDF.write_html(): fixed automatic page break when an image does not have enough vertical space to be rendered on a page/Resources directories are now properly created for each document page. This change ensures better compliance with the PDF specification but results in a slight increase in the size of PDF documents. You can still use the old behavior by setting FPDF().single_resources_object = TrueFPDF.write_html(): fixed incoherent indentation of long <ul> list entries - cf. issue #1073 - thanks to @lcgeneralprojectstop_margin and bottom_margin in HTML2FPDF._new_paragraph() calls are now correctly converted into chosen document units.fpdf.drawing.color_from_hex_string did not test or mention accepting lowercase hex values.FPDF.get_string_width() [issue #1231]RecursionError in some cases when calling FPDF.write_html() inside FPDF.footer() - issue #1222FPDF.write_html(), which used to magically pass instance attributes as arguments.fpdf.TitleStyle has been renamed into fpdf.TextStyleFPDF.write_html(): tag_indents introduced in the last version - Now the indentation can be provided through the tag_styles parameter, using the .l_margin of TextStyle instancesFPDF.local_context() used to treat font_size as a value in points. Now this is the role of font_size_pt, whereas font_size allows to set the font size into chosen document units (specified with FPDF(unit=)) - MR: #1207FPDF.circle() : the previous r parameter, that in fact defined the diameter, has been replaced by a new radius paremeter. The x & y parameters now define the circle center, instead of its top-left corner as it used to be - issue #1245FPDF.table() now raises an error when a single row is too high to be rendered on a single pageFPDF.write_html(): indentation of HTML elements can now be non-integer (float), and is now independent of font size and bullet strings.style attribute in FPDF.add_font()new optional parameter repeat_headings for `FPDF.table()` that indicates whether to print table headings on every page
repeat_headings for FPDF.table() that indicates whether to print table headings on every pageli_prefix_color parameter for FPDF.write_html()start & type attributes of <ol> tags, and type attribute of <ul> tags, when using FPDF.write_html()FPDF.write_html() now accepts a tag_styles parameter to control the font, color & size of HTML elements: <a>, <blockquote>, <li>...FPDF.write_html() now accepts a tag_indents parameter to control, for example, the indent of <blockquote> elementsFPDF.write_html() now honors line-height attributes on <ol> & <li> elements, or the same CSS property in style attributes on those tagscell_fill_mode logic for tables: Set cells background - documentation section. Also added 2 new values: TableCellFillMode.EVEN_ROWS & TableCellFillMode.EVEN_COLUMNS: documentationlevel in class OutlineSection from str to int.FPDF.start_section() - cf. issue #1092dd_tag_indent & li_tag_indent parameters of FPDF.write_html() are replaced by the new tag_indents generic parameter.heading_sizes & pre_code_font parameters of FPDF.write_html() are replaced by the new tag_styles generic parameter.support for elements in SVG elements
<path> elements in SVG <clipPath> elementsbidirectional text shaping - thanks to @andersonhcfpdf2 with mistletoe in order to generate PDF documents from Markdown (link)Table cells that span multiple rows via the rowspan attribute, which can be combined with colspan - thanks to @mjasperseTableSpan.COL and TableSpan.ROW enums that can be used as placeholder table entries to identify span extents - thanks to @mjasperseFPDF._disable_writing() properly disable link writing.FPDF.write_html() now handles linking directly to other pages - thanks to @mjasperseTitleStyle is now rendered as non-bold even when the current font is bold.table() inside the render_toc_function.set_text_shaping(True) & .offset_rendering()border=0 in HTML table - thanks to @mjasperseFPDF.write_html() now properly honors align= attributes in <th> tagsFPDF.multi_cell() to generate fewer PDF component objects - thanks to @mjaspersegutter_width/gutter_height, with spacing applied inside the border similar to HTML tables - thanks to @mjasperse - cf. #1071Table have the same number of columns - thanks to @mjasperseArial → Helvetica, CourierNew → Courer, TimesNewRoman → Times). They will be removed in a later release.Basic support for elements in SVG vector graphics inserted
<image> elements in SVG vector graphics inserted<defs> tags anywhere in the SVG file - thanks to @afriedman412 - cf. #968FPDF.fonts.FontFace: Now has a static combine method that allows overriding a default FontFace (e.g. for specific cells in a table). Unspecified properties of the override FontFace retain the values of the default - thanks to @TedBrookings - cf. #979TextColumns() can now have images inserted (both raster and vector) - thanks to @gmischlerTextColumns() can now advance to the next column with the new new_column() method or a FORM_FEED character (\u000c) in the text - thanks to @gmischlerFPDF.set_font_color() raised a TypeError when used in tablesFPDF.image(x=Align.C) used to fail for SVG images - fixed thanks to @gmischler - cf. #1003keep_aspect_ratio argument.FPDF.write_html() now properly honor the current text font color when styling table cellsFPDF.write_html() delays unescaping data so as not to confuse entity names as nested tagsFPDF.multi_cell() has improved handling of new_x and new_y when padding is non-zero.FPDF.multi_cell(fill=True) now avoids overlapping multiline strings when padding is non-zero..images, .icc_profiles & .image_filter attributes of FPDF instances have been moved inside a nested FPDF.image_cache attribute. Similarly, the FPDF.preload_image() is now a function in the fpdf.image_parsing module: documentationfpdf.svg module now produces WARNING log messages for unsupported SVG tags & attributes.
If those logs annoy you, you can suppress them: logging.getLogger("fpdf.svg").propagate = FalseFPDF.table(): If cell styles are provided for cells in heading rows, combine the cell style as an override with the overall heading style.This release is the first performed from the @py-pdf GitHub org, where fpdf2 migrated. This release also marks the arrival of two new maintainers: Geo
This release is the first performed from the @py-pdf GitHub org, where fpdf2 migrated.
This release also marks the arrival of two new maintainers: Georg Mischler (@gmischler) and Anderson Herzogenrath da Costa (@andersonhc).
text_columns() allows to render text within a single or multiple columns, including height balancing: documentationFPDF.write_html() now supports heading colors defined as attributes (e.g. <h2 color="#00ff00">...)FPDF.table(): Now supports padding in cells : documentationFPDF.table(): Now supports vertical alignment in cells : documentationFPDF.table(): Now supports outer border width for rendering the outer border of the table with a different line-widthFPDF.table(): Now supports multiple heading rows : documentationlivereload to enable a "watch" mode with PDF generation: Combine with livereloadwrite_html() has changed in some aspects. Vertical spacing around headings and paragraphs may be slightly different, and elements at the top of the page don't have any extra spacing above anymore.FPDF.table(): If the height of a row is governed by an image, then the default vertical alignment of the other cells is "center". This was "top".write_html() can now handle formatting tags within paragraphs without adding extra line breaks (except in table cells for now).<pre> and <code> tags is not fixed to 11 pica anymore, but adapts to the preceding text.FPDF.ln(), when called before any text has been written, will now use the current font height instead of doing nothing - cf. issue #937FPDF.image(), when provided a BytesIO instance, does not close it anymore - cf. issue #881set_display_mode() - cf. issue #926FPDF.table(): images no longer overlap with cell borders - cf. issue #892txt parameters of FPDF.cell(), FPDF.multi_cell(), FPDF.text() & FPDF.write() have been renamed to textThis release is the first performed from the @py-pdf GitHub org, where fpdf2 migrated.
This release also marks the arrival of two new maintainers: Georg Mischler (@gmischler) and Anderson Herzogenrath da Costa (@andersonhc).
text_columns() allows to render text within a single or multiple columns, including height balancing: documentation - thanks to @gmischlerFPDF.table(): Now supports padding in cells : documentation - thanks to @RubendeBruinFPDF.table(): Now supports vertical alignment in cells : documentation - thanks to @RubendeBruinFPDF.table(): Now supports outer border width for rendering the outer border of the table with a different line-width - thanks to @RubendeBruinFPDF.table(): Now supports multiple heading rows : documentation - thanks to @SandraFerFPDF.write_html() now supports heading colors defined as attributes (e.g. <h2 color="#00ff00">...) - thanks to @Lucas-Clivereload to enable a "watch" mode while performing PDF generation: Combine with livereload - thanks to @Lucas-CFPDF.write_html(): the formatting output has changed in some aspects. Vertical spacing around headings and paragraphs may be slightly different, and elements at the top of the page don't have any extra spacing above anymore.FPDF.table(): If the height of a row is governed by an image, then the default vertical alignment of the other cells is "center". This was "top".FPDF.table() & FPDF.multi_cell(): when some horizontal padding was set, the text was not given quite enough space - thanks to @gmischlerFPDF.write_html() can now handle formatting tags within paragraphs without adding extra line breaks (except in table cells for now) - thanks to @gmischlerFPDF.write_html(): the font size in HTML <pre> and <code> tags is not fixed to 11 pica anymore, but adapts to the preceding text - thanks to @gmischlerFPDF.ln(), when called before any text has been written, will now use the current font height instead of doing nothing - thanks to @gmischler - cf. issue #937FPDF.image(), when provided a BytesIO instance, does not close it anymore - cf. issue #881 - thanks to @Lucas-Cset_display_mode() - cf. issue #926FPDF.table(): images no longer overlap with cell borders - thanks to @RubendeBruin - cf. issue #892txt parameters of FPDF.cell(), FPDF.multi_cell(), FPDF.text() & FPDF.write() have been renamed to textthe center optional parameter of `FPDF.cell()` is no more deprecated, as it allows for horizontal positioning, which is different from text alignment…
FPDF.set_text_shaping(): new method to perform text shaping using Harfbuzz - documentation - thanks to @andersonhc in PR #820FPDF.mirror() - New method: documentation page - Contributed by @sebastiantiaFPDF.table(): new optional parameters gutter_height, gutter_width and wrapmode. Links can also be added to cells by passing a link parameter to Row.cell()FPDF.multi_cell(): has a new optional center parameter to position the cell horizontally at the center of the page<table> tags: https://pyfpdf.github.io/fpdf2/HTML.htmlFPDF.table(): the colspan setting has been fixed - documentationFPDF.image(): allowing images path starting with data to be passed as inputFPDF.write() & FPDF.write_html() - cf. issue #847FPDF.write_html() - cf. issue #846TextLine- thanks to @Tolker-KU - cf. Pull Request #862center optional parameter of FPDF.cell() is no more deprecated, as it allows for horizontal positioning, which is different from text alignment control with align="C"`FPDF.image()`: CMYK images can now be inserted directly by passing them into the image method. Contributed by @devdev29
FPDF.image(): CMYK images can now be inserted directly by passing them into the image method. Contributed by @devdev29graphs and charts generated using Pygal lib: documentation section - thanks to @ssavi-ictfpdf2 with FastAPI: https://pyfpdf.github.io/fpdf2/UsageInWebAPI.html#FastAPI - thanks to @KamarulAdhaFPDF.write_html(): <table> elements can now be aligned left or right on the page using align=FPDF.write_html(): a custom font can now be specified for <code> & <pre> elements, using the new optional parameter pre_code_fontFPDF.table(): images no more overflow cellsFPDF.table(): text overflow in the last cell of the header row is now properly handledFPDF.table(): when align="RIGHT" is provided, the page right margin is now properly taken in considerationFPDF.write_html() does not render the top row as a header, in bold with a line below, when no <th> are used, in order to be more backward-compatible with earlier versions of fpdf2 - cf. #740split_only optional parameter of FPDF.multi_cell(), which is replaced by two new distincts optional parameters: dry_run & outputremoved a debug print() statement left in output.py:OutputProducer._add_fonts() 🤦♂️ - A rule was also added to .pre-commit-config.yaml to avoid this
print() statement left in output.py:OutputProducer._add_fonts() 🤦♂️ - A rule was also added to .pre-commit-config.yaml to avoid this to happen again.custom fonts can be used with FPDF.table() without triggering a TypeError: cannot pickle 'dict_keys' object - thanks @aeris07 for the bug report
FPDF.table() without triggering a TypeError: cannot pickle 'dict_keys' object - thanks @aeris07 for the bug report<rect> with width / height defined as percentsFPDF.table() without triggering a TypeError: cannot pickle 'dict_keys' object - thanks @aeris07 for the bug report<rect> with width / height defined as percentspython-barcode lib: documentation sectionrenamed fonts.FontStyle to `fonts.FontFace`, and FPDF.use_font_style to `FPDF.use_font_face`, to avoid confusions with FPDF.font_style
fonts.FontStyle to fonts.FontFace, and FPDF.use_font_style to FPDF.use_font_face, to avoid confusions with FPDF.font_stylenew method `FPDF.table()`: documentation
FPDF.table(): documentationFPDF.image() has a new keep_aspect_ratio optional boolean parameter, to fit it inside a given rectangle: documentationFPDF.multi_cell() and FPDF.write() now accept a wrapmode argument for word or character based line wrapping ("WORD"/"CHAR").FPDF.preload_image() & FPDF.use_font_style()FPDF.set_fallback_fonts() allow alternative fonts to be provided if a character on the text is not available on the currently set font - thanks to @andersonhcFPDF.set_link() could not update links generated with add_link()TitleStyle constructor parameters are now effectively optionalfonttoolsFPDF.write_html() now uses the new FPDF.table() method to render <table> tags. As a consequence, vertical space before <table> tags has sometimes been reduced.fpdf2 can now embed SVG files without viewPort or no height / widthCCITTFaxDecode, reducing their size in the PDF document - thanks to @erouxFPDF.write_html() now uses the new FPDF.table() method to render <table> tags. As a consequence, it does not support the height attribute defined on <td> / <th> tags anymore, nor height / width attributes defined on <img> tags inside cells, nor width attributes defined on <thead> / <tfoot> tags.support for PDF encryption (RC4 and AES-128): documentation page - thanks to @andersonhc
FPDF.skew() - New method: documentation page - thanks to @erap129FPDF.image(): the x parameter now accepts a value of "C" / Align.C / "R" / Align.R to horizontally position the image centered or aligned rightFPDF.image(): dimensions can now be provided to set the intrinsic image width & height before storing it in the PDFFPDF.cell() & FPDF.multi_cell(): support for []() hyperlinks when markdown=TrueFPDF.write_html(): support for line-height attribute of paragraph (<p>) - thanks to @Bubbu0129FPDF.add_link() creates a link to the current page by default, and now accepts optional parameters: x, y, page & zoom.
Hence calling set_link() is not needed anymore after creating a link with add_link().FPDF.write_html() now generates warnings for unclosed HTML tags, unless warn_on_tags_not_matching=False is setFPDF.write_html(): a ValueError: Incoherent hierarchy could be raised with some headings hierarchyFPDF.write_html(): <img> without height attribute overlaps with the following content #632 - thanks to @Bubbu0129FPDF.image(): performance issue with adding large images with FlateDecode image filter #644 - thanks to @Markovvn1FPDF.add_font(): fix support for upper case font file name #638 - thanks to @CY-QiuHTMLMixin is deprecated, and not needed anymore: the `write_html()` method is now natively available in the `FPDF` class - thanks to @yk-jp
.default_page_dimensions property on FPDF instances<dl>), description titles (<dt>), description details (<dd>) and code blocks (<code></code>) in write_html() - thanks to @yk-jp & @seanpmulhollandimage.mode == '1') thanks to @GerardoAllendefpdf2 resource usagefpdf2, added by @devdev29: https://pyfpdf.github.io/fpdf2/CombineWithPyPDF2.htmlfpdf2: https://pyfpdf.github.io/fpdf2/TemplatingWithJinja.htmlHTMLMixin is deprecated, and not needed anymore: the write_html() method is now natively available in the FPDF class - thanks to @yk-jpopen() & close() methods, that were only used internally and should never have been called by end-user codeFPDF.state, which was an instance of the DocumentState enum, and has been replaced by moving the final rendering logic into a new fpdf.output modulecell(), ln() applied a line height of zero #601multi_cell() with max_line_height to render multiline text, the last line is now rendered like all the othersinsert_toc_placeholder() usage with footer() and {{nb}}; #548stroke-width attribute values with an explicit unit, thanks to @gmischler; #526width and height attributes, thanks to @darioackermann; #555write_html() method now correctly handles whitespace when parsing HTML. <pre></pre> blocks still maintain spaces, tabs and line breaks.FPDF.add_font() is now optional: if it is not provided, the base name of the fname font path is used to define the font family. Hence pdf.add_font(fname="fonts/NotoSansArabic.ttf") will define a font named NotoSansArabic.embed_file() is now a PDFEmbeddedFile, not a string, but the internal file name can be retrieved through its .basename propertyget_y() & local_context() inside unbreakable() as it is currently not supported; #557Added support for subscript, superscript, nominator and denominator char positioning as well as and HTML tags, thanks to @gmischler: link to documenta
<sub> and <sup> HTML tags, thanks to @gmischler: link to documentationset_page_background(): new method added by @semaeostomea: link to documentationembed_file() & file_attachment_annotation(): new methods to add file attachments - link to documentationset_char_spacing() allows to increase the spacing between individual characters, thanks to @gmischler: link to documentationfpdf2 now uses fontTools to read and embed fonts in the PDF, thanks to @gmischler and @RedShyarc() not longer renders artefacts at intersection point, thanks to @Jmillan-Dev; #488write_html():
CreationDate of PDFs & embedded files now includes the system timezone<sub> and <sup> HTML tags, thanks to @gmischler: link to documentationset_page_background(): new method added by @semaeostomea: link to documentationembed_file() & file_attachment_annotation(): new methods to add file attachments - link to documentationset_char_spacing() allows to increase the spacing between individual characters, thanks to @gmischler: link to documentationfpdf2 now uses fontTools to read and embed fonts in the PDF, thanks to @gmischler and @RedShyarc() not longer renders artefacts at intersection point, thanks to @Jmillan-Dev; #488write_html():
CreationDate of PDFs & embedded files now includes the system timezonenew methods to allow signing PDF documents: link to docs
rgb() syntax in SVG images - cf. #480/ID is now inserted in the trailer dictionary of all PDF documents generated.
This ID can be controlled through the new file_id() method.font_stretching doesn't make text spill out of multi_cell() and write() boundaries anymore, thanks to @gmischlerlocal_context() now always restores the correct font settings after finishing, thanks to @gmischlera new option align="X" to .cell() and .multi_cell() allows to center text around the current x position, thanks to @gmischler
align="X" to .cell() and .multi_cell() allows to center text around the current x position, thanks to @gmischlerAnnotationName and AnnotationFlags onto text_annotation()style="..." attribute), thanks to @RedShyFPDF.star(): new method added to draw regular stars, thanks to @digidigital and @RedShyFPDF.ink_annotation(): new method added to add path annotationsTextMarkupTyperound_corners to FPDF.rect() that allows to draw rectangles with round corners: link to docs - thanks to @gonzalobarbarannew FPDF.page_mode property, allowing to display a PDF in full screen: link to docs
FPDF.page_mode property, allowing to display a PDF in full screen: link to docsFPDF.viewer_preferences property: link to docsprint() statement (multi_cell: new_x=... new_y=...) that had been left in multi_cell() method 🤦♂️cell() & multi_cell(), which was broken in 2.5.2regular_polygon() is called with style="f",
the shape outline is not drawn anymore. Use style="DF" to also draw a line around its perimeter.fill parameter of the polygon()
& polyline() methods have been replaced by a style argument,
offering more controlsupport for .pkl files passed to add_font(). This was deprecated since v2.5.1. As a consequence, fpdf2 no more uses the pickle module.
round_clip() & elliptic_clip() image clipping methods: link to docsCoerciveEnum subclasses have been added: Align & RenderStylefpdf2 with Flask, streamlit, AWS lambdas: link to docsTextMode, XPos & YPos now inherit from CoerciveEnum and hence can simply be passed as string parameters.multi_cell() without enough horizontal space - cf. #389.pkl files passed to add_font(). This was deprecated since v2.5.1.
As a consequence, fpdf2 no more uses the pickle module.The parameter ln to cell() and multi_cell() is now deprecated, use new_x and new_y instead.
new_x and new_y for cell() and multi_cell(), replacing ln=0, thanks to @gmischleradd_highlight() method to insert highlight annotations: documentationoffset_rendering() method: documentation.text_mode property: documentationunbreakable() section, which is not supportedlocal_context() can now "scope" even more properties, like blend_mode: documentationmulti_cell(align="J") is given text with multiple paragraphs (text followed by an empty line) at once, it now renders the last line of each paragraph left-aligned,
instead of just the very last line (cf. #364), thanks to @gmischlermulti_cell() always renders a cell, even if txt is an empty string - cf. #349multi_cell(..., split_only=True) inside an unbreakable section - cf. #359ln to cell() and multi_cell() is now deprecated, use new_x and new_y instead.center to cell() is now deprecated, use align="C" instead.DeprecationWarnings are not displayed by Python by default.
Hence, every time you use a newer version of fpdf2, we strongly encourage you to execute your scripts
with the -Wd option (cf. documentation)
in order to get warned about deprecated features used in your code.
This can also be enabled programmatically with warnings.simplefilter('default', DeprecationWarning).
…the uni optional argument of FPDF.add_font() are deprecated. The fpdf.fpdf.load_cache function has also been removed.
\u00ad) break in write(), cell() & multi_cell() calls - thanks @oleksii-shyman & @gmischler!
Documentation: Line breaksborb & fpdf2: Creating a borb.pdf.document.Document from a FPDF instancewrite() now supports soft hyphen characters, thanks to @gmischlerfname is now a required parameter for FPDF.add_font()image() method now insert .svg images as PDF paths_substitute_page_number() has been lowered from INFO to DEBUGtext_color or fill_colorget_string_width() with unicode fonts and Markdown enabled,
resulting in calls to cell() / multi_cell() with align="R" to display nothing - thanks @mcerveny for the fix!pickle module, has been removed, for security reasons,
and because it provided little performance gain, and only for specific use cases - cf. issue #345.
That means that the font_cache_dir optional parameter of fpdf.FPDF constructor
and the uni optional argument of FPDF.add_font() are deprecated.
The fpdf.fpdf.load_cache function has also been removed.To be extra clear: uni=True can now be removed from all calls to FPDF.add_font().
If the value of the fname argument passed to add_font() ends with .ttf, it is considered a TrueType font.
Thanks to @torque for contributing this massive new feature:
Thanks to @torque for contributing this massive new feature:
fpdf.drawing API for composing paths from an arbitrary sequence of lines and curves.fpdf.svg.convert_svg_to_drawing function to support converting basic scalable vector graphics (SVG) images to PDF paths.will_page_break() & accept_page_break are not invoked anymore during a call to multi_cell(split_only=True)dashed_line() is now deprecated in favor of set_dash_pattern()
New FPDF.pages_count property, thanks to @paulacampigotto
Temporary changes to graphics state variables are now possible using with FPDF.local_context():, thanks to @gmischler
a mechanism to detect & downscale oversized images, cf. documentation. Feedbacks on this new feature are welcome!
New set_dash_pattern(), which works with all lines and curves, thanks to @gmischler.
Templates now support drawing ellipses, thanks to @gmischler
New documentation on how to display equations, using Google Charts or matplotlib: Maths
The whole documentation can now be downloaded as a PDF: fpdf2-manual.pdf
New sections have been added to the tutorial, thanks to @portfedh:
New translation of the tutorial in Hindi, thanks to @Mridulbirla13: हिंदी संस्करण; Deutsch, thanks to @digidigital; and Italian thanks to @xit4; Русский thanks to @AABur; and português thanks to @fuscati; français, thanks to @Tititesouris
While images transparency is still handled by default through the use of SMask,
this can be disabled by setting pdf.allow_images_transparency = False
in order to allow compliance with PDF/A-1
FPDF.arc: new method added to draw arcs in a PDF document.
FPDF.solid_arc: new method added to draw solid arcs in a PDF document. A solid arc combines an arc and a triangle to form a pie slice.
FPDF.regular_polygon: new method added, thanks to @bettman-latin
SMask entry is inserted for images that are fully opaque
(= with an alpha channel containing only 0xff characters)rect, ellipse & circle all have a style parameter in common.
They now all properly accept a value of "D" and raise a ValueError for invalid values.dashed_line() is now deprecated in favor of set_dash_pattern()ensure support for old field names in Template.code39 for backward compatibility
Template.code39 for backward compatibilityTemplate() has gained a more flexible cousin FlexTemplate(), thanks to @gmischler
Template() has gained a more flexible cousin FlexTemplate(), thanks to @gmischlermulti_cell(), thanks to Yeshi NamkhaiFPDF.image, thanks to @MWhatsUppystrich lib: documentation section,
thanks to @MWhatsUpwrite_html: headings (<h1>, <h2>...) relative sizes can now be configured through an optional heading_sizes parameterHTML2FPDF can now easily be used by setting FPDF.HTML2FPDF_CLASS,
cf. documentationTemplate: split_multicell() will not write spurious font data to the target document anymore, thanks to @gmischlerTemplate: rotation now should work correctly in all situations, thanks to @gmischlerwrite_html: headings (<h1>, <h2>...) can now contain non-ASCII characters without triggering a UnicodeEncodeErrorTemplate: CSV column types are now safely parsed, thanks to @gmischlercell(..., markdown=True) "leaked" its final style (bold / italics / underline) onto the following cellswrite_html: the line height of headings (<h1>, <h2>...) is now properly scaled with its font sizeFPDF methods should not be used inside a rotation context, or things can get broken.
This is now forbidden: an exception is now raised in those cases.Template: code39 barcode input field names changed from x/y/w/h to x1/y1/y2/sizesupport for emojis! Me precisely unicode characters above 0xFFFF in general, thanks to @moe-25
0xFFFF in general, thanks to @moe-25Template can now insert justified textget_scale_factor utility function to obtain FPDF.k without having to create a documentconvert_unit utility function to convert a number, x,y point, or list of x,y points from one unit to another unitfpdf.FPDF() constructor now accepts ints or floats as a unit, and raises a ValueError if an invalid unit is provided.Template background property is now properly supported - #203
⚠️ Beware that its default value changed from 0 to 0xffffff, as a value of zero would render the background as black.Template.parse_csv: preserving numeric values when using CSV based templates - #205* characters.
This has been fixed, and a warning is now triggered by the FPDF.code39 method when those characters are missing.uni=True when loading cached fonts (page numbering was missing digits)disable font caching when fpdf.FPDF constructor invoked with font_cache_dir=None, thanks to @moe-25 !
fpdf.FPDF constructor invoked with font_cache_dir=None, thanks to @moe-25 !FPDF.circle: new method added, thanks to @viraj-shah18 !HTMLMixin / HTML2FPDF: support setting HTML font colors by name and short hex codesFPDF.will_page_break
utility method to let users know in advance when adding an elemnt will trigger a page break.
This can be useful to repeat table headers on each page for exemple,
cf. documentation on Tables.FPDF.set_link now support a new optional x parameter to set the horizontal position after following the linkfpdf.Template was used to render QRCodes, due to a forced conversion to string (#175)erroneous page breaks occured for full-width / full-height images
the FPDF.set_doc_option() method is deprecated in favour of just setting the core_fonts_encoding property on an instance of FPDF
fpdf2 uses the newly supported DCTDecode image filter for JPEG images,
instead of FlateDecode before, in order to improve the compression ratio without any image quality loss.
On test images, this reduced the size of embeded JPEG images by 90%.FPDF.cell: the w (width) parameter becomes optional, with a default value of None, meaning to generate a cell with the size of the text content providedh (height) parameter of the cell, multi_cell & write methods gets a default value change, None, meaning to use the current font sizew & h parameters of the FPDF.text_annotation() methodFPDF.add_action() method, documented in the Annotations sectionFPDF.cell: new optional markdown=True parameter that enables basic Markdown-like styling: **bold**, __italics__, --underlined--FPDF.cell: new optional boolean center parameter that positions the cell horizontallyFPDF.set_link: new optional zoom parameter that sets the zoom level after following the link.
Currently ignored by Sumatra PDF Reader, but observed by Adobe Acrobat reader.HTMLMixin / HTML2FPDF: now support align="justify"FPDF.image_filter to control the image filters used for imagesFPDF.add_page: new optional duration & transition parameters
used for presentations (documentation page)fpdf.template, using type="C39"Undefined font error when using write_html with unicode bold or italics fontsFPDF.set_doc_option() method is deprecated in favour of just setting the core_fonts_encoding property
on an instance of FPDFfpdf.SYSTEM_TTFONTS configurable module constant is now ignoreda bug in the deprecation module that prevented to configure fpdf2 constants at the module level
deprecation module that prevented to configure fpdf2 constants at the module levela "fake duplicates" bug when a Pillow.Image.Image was passed to FPDF.image
Pillow.Image.Image was passed to FPDF.imagenew features: document outline & table of contents! Check out the new dedicated documentation page for more information
text_annotation to insert... Text AnnotationsFPDF.image now also accepts an io.BytesIO as inputHTMLMixin / HTML2FPDF: properly handling <img> inside <td> & allowing to center them horizontallyFPDF.text_annotation to insert... Text AnnotationsFPDF.image now also accepts an io.BytesIO as inputwrite_html: properly handling <img> inside <td> & allowing to center them horizontallymade bullets & indentation configurable through class attributes, instance attributes or optional method arguments, _cf._ `test_customize_ul`
FPDF.set_xmp_metadata<li> bullets & indentation configurable through class attributes, instance attributes or optional method arguments, cf. test_customize_ulFPDF.multi_cell: line wrapping with justified content and unicode fonts, cf. #118FPDF.multi_cell: when ln=3, automatic page breaks now behave correctly at the bottom of pagesFPDF.polyline & FPDF.polygon : new methods added by @uovodikiwi - thanks!
FPDF.polyline & FPDF.polygon : new methods added by @uovodikiwi - thanks!FPDF.set_margin : new method to set the document right, left, top & bottom margins to the same value at onceFPDF.image now accepts new optional title & alt_text parameters defining the image title
and alternative text describing it, for accessibility purposesFPDF.link now honor its alt_text optional parameter and this alternative text describing links
is now properly included in the resulting PDF documentFPDF.set_langFPDF.unbreakable so that no extra page jump is performed when FPDF.multi_cell is called inside this contextfpdf.FPDF_CACHE_MODE & fpdf.FPDF_CACHE_DIR in favor of a configurable new font_cache_dir optional argument of the fpdf.FPDF constructorMany thanks to @eumiro & @fbernhart for their contributions to make fpdf2 cleaner!
Many thanks to @eumiro & @fbernhart for their contributions to make fpdf2 cleaner!
Check this blog post for an explanation on this release name.
FPDF.unbreakable : a new method providing a context-manager in which automatic page breaks are disabled.
cf. https://pyfpdf.github.io/fpdf2/PageBreaks.htmlFPDF.epw & FPDF.eph : new @property methods to retrieve the effective page width / height, that is the page width / height minus its horizontal / vertical margins.FPDF.image now accepts also a Pillow.Image.Image as inputFPDF.multi_cell parameters evolve in order to generate tables with multiline text in cells:
ln parameter now accepts a value of 3 that sets the new position to the right without altering vertical offsetmax_line_height parameter sets a maximum height of each sub-cell generatedFPDF.alias_nb_pages: fixed this feature that was broken since v2.0.6FPDF.set_font: fixed a bug where calling it several times, with & without the same parameters,
prevented strings passed first to the text-rendering methods to be displayed.dest parameter of FPDF.output methodnew unit tests, a code formatter (black) and a linter (pylint) to improve code quality
black) and a linter (pylint) to improve code qualitytable_line_separators for HTMLMixin.write_html & underlying HTML2FPDF constructor.font Python files, that relied on a call to exectype parameter of FPDF.image methodinfile parameter of Template constructordest parameter of Template.render methodJan 11, 2021 1 file Pre-release
Jan 11, 2021 1 file
Pre-release
Jan 8, 2021 2 files Pre-release
Jan 8, 2021 2 files
Pre-release
Jan 7, 2021 2 files Yanked
Jan 7, 2021 2 files
Yanked
Deprecating .rotate() and introducing .rotation() context manager
User defined path to font is ignorednumpyDec 7, 2020 2 files
Yanked reason: Please install fpdf2==2.0.6 for a less buggy experience.
Pre-release
Nov 20, 2020 2 files
Nov 20, 2020 2 files
### Added * Python 3.9 is now supported
new specific exceptions: FPDFException & FPDFPageFormatException
FPDFException & FPDFPageFormatExceptionimage_parsing modulecgfrost!images centering - thanks cgfrost!
cgfrost!urlopen in image_parsing modulesix library to maintain python2 compatibilityAbility to use a BytesIO buffer directly. This can simplify loading matplotlib plots into the PDF.
BytesIO buffer directly. This can simplify loading matplotlib plots into the PDF.load_resource now return argument if type is BytesIO, else load.introduced a dependency to numpy to improve performances by replacing pixel regexes in image parsing (s/o @pennersr)
numpy to improve performances by replacing pixel regexes in image parsing (s/o @pennersr)support for more recent Python versions
/Transparency dictaccept_page_break into a propertyunittest libflake8May 4, 2017 1 file
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page
"PyPI", "Python Package Index", and the blocks logos are registered trademarks of the Python Software Foundation .
© 2026 Python Software Foundation
Site map
Deployed from 2a05d27
Your coding agent can read these notes before it upgrades. Set up the MCP server →