Export PDF from your editor

Available in Start planBetav0.3.0

Use Tiptap's @tiptap-pro/extension-export-pdf to export your editor's content as a .pdf file. This extension integrates PDF export functionality into your editor by sending the document to the Tiptap convert service for conversion.

You can also use the REST API instead if you'd prefer to handle the conversion on your end.

Install the PDF Export extension

The Conversion extensions are published in Tiptap's private npm registry. Integrate the extensions by following the private registry guide.

Once done you can install and import the Export PDF extension package.

npm i @tiptap-pro/extension-export-pdf
import { ExportPdf } from '@tiptap-pro/extension-export-pdf'

Configuring the extension

The ExportPdf extension can be configured with an ExportPdfOptions (object) as an argument to the configure method with the following properties:

import { ExportPdf } from '@tiptap-pro/extension-export-pdf'

const editor = new Editor({
  extensions: [
    // Other extensions ...
    ExportPdf.configure({
      endpoint: 'https://api.tiptap.dev/v2/convert',
      token: 'YOUR_TOKEN',
      appId: 'YOUR_APP_ID',
      styleOverrides: {},
      headers: {},
      footers: {},
      pageSize: { width: '21cm', height: '29.7cm' },
      pageMargins: { top: '1cm', bottom: '1cm', left: '1cm', right: '1cm' },
      customNodes: [],
      onCompleteExport: (result) => {
        // Handle the exported Blob
      },
    }),
    // Other extensions ...
  ],
})
ParameterTypeDescriptionDefault
endpointstringThe Tiptap API endpoint for conversion'https://api.tiptap.dev/v2/convert'
tokenstringThe Tiptap JWT for authentication''
appIdstringThe Tiptap App ID for authentication''
styleOverridesRecord<string, string>Style overrides to apply to the exportundefined
headersHeaderConfigHeader configuration for the exported documentundefined
footersFooterConfigFooter configuration for the exported documentundefined
pageSizePageSizePage size configurationundefined
pageMarginsPageMarginsPage margins configurationundefined
customNodesCustomNodeDefinition[]Custom node definitions for DOCX-based conversion (requires @tiptap-pro/extension-export-docx)undefined
customFontsCustomFont[]Custom font files to provision for PDF export (on-premises only)undefined
onCompleteExport(result: Blob) => voidCallback that receives the exported file as a BlobThrows error if not provided
onExportError(error: Error) => voidOptional callback invoked when the export pipeline rejects (failed dynamic import, failed DOCX conversion, network error, non-OK response). When omitted, errors are logged via console.error.undefined

Every header and footer slot (default, first, even) accepts any of five shapes; pick whichever matches your data. The first three work with @tiptap-pro/extension-export-pdf alone; the last two require @tiptap-pro/extension-export-docx to also be installed (they take the DOCX-first export path, which is lazy-loaded so PDF-only consumers aren't affected).

ShapeExampleNotes
Plain text'Company name, 2026'Unstyled header/footer.
Stringified Tiptap JSONContentJSON.stringify(myHeaderDoc)Pre-serialized Tiptap node. Rich formatting preserved.
Tiptap JSONContent object{ type: 'doc', content: [/* … */] }Rich Tiptap node passed directly. No stringification needed.
docx Header / Footer instancenew Docx.Header({ children: [/* … */] })Full DOCX-level control. Requires the DOCX extension.
Async factory returning Header / Footer() => convertHeader({ node })Built on demand at export time. Typical use: convertHeader / convertFooter. Requires the DOCX extension.

Tiptap JSONContent objects must include a type field. That's the runtime discriminator the extension uses to tell a Tiptap node apart from a docx instance. Objects without type that aren't Header / Footer instances are dropped with a console.warn pointing at the offending value, not forwarded to the DOCX serializer.

In TypeScript these shapes collapse to two aliases (the type requirement is encoded in TiptapNodeContent):

import type { JSONContent } from '@tiptap/core'
import type { Footer, Header } from 'docx'

type TiptapNodeContent = JSONContent & { type: string }

type HeaderSlotValue = string | TiptapNodeContent | Header | (() => Promise<Header>)
type FooterSlotValue = string | TiptapNodeContent | Footer | (() => Promise<Footer>)

HeaderConfig

PropertyTypeDescription
evenAndOddHeadersbooleanWhether to use different headers for odd and even pages.
differentFirstPagebooleanWhether to use a different header on the first page. When true, the first value is used on page one instead of default.
defaultHeaderSlotValueThe standard default header on every page, or the header on odd pages when evenAndOddHeaders is active.
firstHeaderSlotValueThe header on the first page. Only used when differentFirstPage is true.
evenHeaderSlotValueThe header on even pages. Only used when evenAndOddHeaders is true.

FooterConfig

PropertyTypeDescription
evenAndOddFootersbooleanWhether to use different footers for odd and even pages.
differentFirstPagebooleanWhether to use a different footer on the first page. When true, the first value is used on page one instead of default.
defaultFooterSlotValueThe standard default footer on every page, or the footer on odd pages when evenAndOddFooters is active.
firstFooterSlotValueThe footer on the first page. Only used when differentFirstPage is true.
evenFooterSlotValueThe footer on even pages. Only used when evenAndOddFooters is true.

PageSize

PropertyTypeDescriptionDefault
widthstringThe width of the page. Must be a positive number followed by a valid unit (cm, in, pt, pc, mm, px)."21cm"
heightstringThe height of the page. Must be a positive number followed by a valid unit (cm, in, pt, pc, mm, px)."29.7cm"

PageMargins

PropertyTypeDescriptionDefault
topstringThe top margin of the page. Can be negative. Must be a number followed by a valid unit (cm, in, pt, pc, mm, px)."1cm"
bottomstringThe bottom margin of the page. Can be negative. Must be a number followed by a valid unit (cm, in, pt, pc, mm, px)."1cm"
leftstringThe left margin of the page. Must be a positive number followed by a valid unit (cm, in, pt, pc, mm, px)."1cm"
rightstringThe right margin of the page. Must be a positive number followed by a valid unit (cm, in, pt, pc, mm, px)."1cm"

CustomFont

On-premises only

Custom fonts are only available in on-premises deployments. If you're interested in using custom fonts with Tiptap's cloud service, please contact us about our Enterprise plan.

PropertyTypeDescription
urlstringHTTPS URL pointing directly to a .ttf or .woff2 font file
fontFamilystringFont family name as used in the document

Export a PDF file

With the extension installed, you can export your editor's content to .pdf using the exportPdf command.

/**
 * Export the current document as a PDF file via the Tiptap convert service.
 *
 * @param options - All extension-level options can be overridden per-invocation
 * @example editor.commands.exportPdf({ onCompleteExport: (result) => {} })
 */
exportPdf: (options?: ExportPdfCommandOptions) => ReturnType

The ExportPdfCommandOptions interface extends ExportPdfOptions, so every configuration option can be overridden per-command invocation:

PropertyTypeDescription
endpointstringOverride the API endpoint for this specific export
tokenstringOverride the JWT token for this specific export
appIdstringOverride the App ID for this specific export
styleOverridesRecord<string, string>Override style overrides for this specific export
headersHeaderConfigOverride header configuration for this specific export
footersFooterConfigOverride footer configuration for this specific export
pageSizePageSizeOverride page size for this specific export
pageMarginsPageMarginsOverride page margins for this specific export
customNodesCustomNodeDefinition[]Override custom node definitions for this specific export
customFontsCustomFont[]Override custom fonts for this specific export (on-premises only)
onCompleteExport(result: Blob) => voidOverride the callback for this specific export
onExportError(error: Error) => voidOverride the error handler for this specific export
import { ExportPdf } from '@tiptap-pro/extension-export-pdf'

const editor = new Editor({
  extensions: [
    // Other extensions ...
    ExportPdf.configure({
      token: 'YOUR_TOKEN',
      appId: 'YOUR_APP_ID',
      onCompleteExport(result) {
        // Download the PDF file
        const url = URL.createObjectURL(result)
        const a = document.createElement('a')

        a.href = url
        a.download = 'document.pdf'
        a.click()

        URL.revokeObjectURL(url)
      },
    }),
    // Other extensions ...
  ],
})

// Use the extension-level callback
editor.chain().exportPdf().run()

// Or override options for a specific export
editor
  .chain()
  .exportPdf({
    pageSize: { width: '8.5in', height: '11in' },
    onCompleteExport(result) {
      // Custom handling for this specific export
      const url = URL.createObjectURL(result)
      window.open(url)
    },
  })
  .run()

How it works

When you call exportPdf, the extension serializes the editor's document to JSON and sends it to the Tiptap convert service along with any configured options (style overrides, page layout, headers, footers, custom fonts). The service converts the document to PDF and returns it as a binary blob. The onCompleteExport callback receives this blob directly, which you can then download or process as needed. Errors are thrown as exceptions rather than passed through the callback.

Custom fonts

On-premises only

Custom fonts are only available in on-premises deployments. If you're interested in using custom fonts with Tiptap's cloud service, please contact us about our Enterprise plan.

The PDF export supports custom fonts for on-premises deployments. You can provision custom fonts by providing an array of font URLs that the conversion service will download and use when generating the PDF.

Font files must be .ttf or .woff2 format and accessible via HTTPS. The fontFamily must match the font family name used in your document's text styles.

ExportPdf.configure({
  token: 'YOUR_TOKEN',
  appId: 'YOUR_APP_ID',
  customFonts: [
    {
      url: 'https://your-cdn.com/fonts/CustomFont-Regular.ttf',
      fontFamily: 'Custom Font',
    },
    {
      url: 'https://your-cdn.com/fonts/CustomFont-Bold.ttf',
      fontFamily: 'Custom Font',
    },
  ],
  onCompleteExport(result) {
    // Handle the exported PDF
  },
})

You can also override custom fonts per-command invocation:

editor
  .chain()
  .exportPdf({
    customFonts: [
      {
        url: 'https://your-cdn.com/fonts/SpecialFont.woff2',
        fontFamily: 'Special Font',
      },
    ],
  })
  .run()

What to expect

  • Authentication required. The export sends the document to the Convert service, which requires a JWT (token) and your App ID. Generate JWTs server-side; never embed your secret key in the browser. See the Conversion install guide.
  • HTTP responses you may need to handle: 401 (missing or invalid JWT), 403 (the operation isn't permitted for your app — most often a format your plan doesn't include, or customFonts against the cloud plan), 5xx (transient server-side error; retry with backoff).
  • Custom fonts are an Enterprise / on-prem feature. In the cloud plan, requests carrying customFonts return 403. To enable them, contact us about an Enterprise plan or run an on-prem deployment.
  • Each request is processed end-to-end before responding. Very large documents may take longer to return; size the request timeouts on your side accordingly.

What not to expect

  • Round-trip identity from DOCX → PDF. PDF is a fixed-layout format; Word and the Convert service use different layout engines, so visual output may differ in subtle ways from Word's PDF print.
  • Pixel-perfect Word match for complex layouts — especially multi-column sections, RTL text, or content that relied on Word-specific layout quirks.
  • Editing in the resulting PDF. PDF export is one-way. To preserve editability, export to DOCX as well.

Support & Limitations

FeatureSupport
Text content✓ Basic text, spacing, punctuation
Text formatting✓ Bold, italic, underline, strikethrough, alignment, line height
Block elements✓ Paragraphs, headings (1–6), blockquotes, ordered and unordered lists
Tables✓ Basic structure, header rows, colspan
Links✓ Hyperlinks
Media (Images)✓ Embedded images, size preserved
Styles✓ Font families*, Font colors, font sizes, background colors, line heights
Custom Fonts✓ On-premises only (.ttf and .woff2)
Headers & Footers
Math
Page Breaks
Sections
Footnotes & Endnotes
Comments & Revisions
Table of Contents
Advanced Formatting✗ Columns, text direction, forms, macros, embedded scripts
Metadata
Text Boxes, Shapes, SmartArt
  • Font families are supported when using Google Fonts (automatically available) or custom fonts provisioned via the customFonts option (on-premises only).

For a detailed per-feature breakdown, see the Supported features matrix. Note that element overrides (paragraphOverrides, textRunOverrides, tableOverrides, tableCellOverrides, imageOverrides) available in the DOCX export extension are not passed through to the PDF conversion.