Polotno
Export & Import

PDF Export

Export raster and vector PDFs from Polotno, with bleed, crop marks, PDF/X-1a, and spot color support

Polotno offers two PDF export paths:

  • Rasterstore.saveAsPDF() / store.toPDFDataURL() in the browser, or polotno-node on the server. Each page is a flattened image embedded in the PDF.
  • Vector@polotno/pdf-export (browser or Node), or the Cloud Render API with vector: true. Resolution-independent output with selectable text.

Try it without code: The SVG to PDF converter exposes both options — it ships vector by default via @polotno/pdf-export/browser and offers a one-click bitmap fallback. Drop a file and try both before integrating.

Choosing raster vs vector

RasterVector
OutputFlattened image per pageSelectable text, scalable shapes
Visual fidelityIdentical to canvasMay differ slightly (font shaping, effects)
File sizeLarger at high pixelRatioSmaller, resolution-independent
Print complianceGood with high pixelRatioRequired for PDF/X-1a, spot colors
Where it runsBrowser, or polotno-node on the serverBrowser, Node, or Cloud Render API
Server requiredNo (browser path)No (browser path); PDF/X-1a needs Node + Ghostscript

Pick raster when you need pixel-perfect parity with the editor canvas. Pick vector for selectable text, smaller files, or print-shop deliverables (PDF/X-1a, spot inks, foils). Both can run fully client-side now — vector via the @polotno/pdf-export/browser entry.


Raster export

Browser-side export via store.saveAsPDF(). Same options apply to store.toPDFDataURL().

Quick start

await store.saveAsPDF({
  fileName: 'design.pdf',
  includeBleed: true,
  cropMarkSize: 20,
  pixelRatio: 2,
});

Bleed and crop marks

Bleed is the extra ink area beyond the trim edge. Crop marks indicate where the print shop should cut.

// set bleed on the page
store.activePage.set({ bleed: 35 }); // 35px

// show bleed area on the canvas (optional, for editor preview)
store.toggleBleed(true);

// export
await store.saveAsPDF({
  includeBleed: true,
  cropMarkSize: 20, // crop mark length in pixels
});

See Page Bleed for working with bleed in the editor.

Quality

Use pixelRatio to control resolution. dpi affects PDF page dimensions, not image quality.

await store.saveAsPDF({ pixelRatio: 2 }); // recommended for print
await store.saveAsPDF({ pixelRatio: 4 }); // ultra-high

See Units and Measures for DPI details.

Options

await store.saveAsPDF({
  fileName: 'design.pdf',
  includeBleed: true,
  cropMarkSize: 20,
  pixelRatio: 2,
  onProgress: (progress) => console.log(progress),
});

See Store API for the complete reference.


Vector export

Three ways to produce vector PDFs. All accept the same Polotno JSON and produce equivalent output for the same input — pick the one that matches your hosting model.

Browser package: @polotno/pdf-export/browser

Convert a design to a vector PDF entirely in the user's browser — no server, no Ghostscript, no API key.

npm install @polotno/pdf-export
import { jsonToPDFBlob } from '@polotno/pdf-export/browser';

async function exportToPDF(store) {
  const blob = await jsonToPDFBlob(store.toJSON());
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'design.pdf';
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(url);
}

The browser entry also exports jsonToPDFBytes(json, attrs): Promise<Uint8Array> for cases where you want raw bytes (IndexedDB, navigator.share, WebTransport, etc.).

CORS

When the design references remote images, fonts, or SVG sources, the browser fetches those at export time. They must be reachable with CORS:

  • Google Fonts (fonts.googleapis.com and fonts.gstatic.com) work out of the box.
  • Custom asset URLs must be served with Access-Control-Allow-Origin: * (or your origin), or pre-fetched and inlined as data: URLs in the JSON.

Browser limitations

The browser entry does not support attrs.pdfx1a or attrs.validate — those rely on Ghostscript, which has no browser equivalent. Pass them and you'll get a clear runtime error pointing at the Node entry. For PDF/X-1a, spot colors, and Ghostscript-backed validation, see the Node section below.

Cloud Render API

Hosted rendering. Send the JSON as a render job with format: 'pdf' and vector: true.

const req = await fetch('https://api.polotno.com/api/renders?KEY=YOUR_API_KEY', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    design: store.toJSON(),
    format: 'pdf',
    vector: true,
  }),
});

See Cloud Render API for full options, polling, webhooks, and CMYK color profiles.

Node package: @polotno/pdf-export

Run the conversion fully offline inside Node 18+. Fits CI jobs, backend services, and desktop tools. Required for PDF/X-1a print-ready output and Ghostscript-backed spot colors.

npm install @polotno/pdf-export
import fs from 'fs/promises';
import { jsonToPDF } from '@polotno/pdf-export';

const data = JSON.parse(await fs.readFile('./polotno.json', 'utf-8'));

await jsonToPDF(data, './output.pdf');

jsonToPDFBytes(data, attrs): Promise<Uint8Array> is also exported on the Node entry — useful when you want raw bytes (to upload, attach, etc.) without writing to disk.

Bleed and crop marks

Set bleed (pixels) on each page in the JSON, then enable bleed and crop marks at export time.

// JSON
const data = {
  width: 1080,
  height: 1080,
  pages: [{ background: '...', bleed: 36, children: [/* ... */] }],
};

// export
await jsonToPDF(data, './print-ready.pdf', {
  pdfx1a: true,
  includeBleed: true,
  cropMarkSize: 18, // reserve 18px around the bleed for crop marks
});

When includeBleed or cropMarkSize is set, the output PDF carries correct PDF/X page boxes:

  • MediaBox — full sheet (trim + bleed + crop-mark margin)
  • BleedBox — trim + bleed (where ink may cover)
  • TrimBox — final cut size
  • ArtBox — same as TrimBox

TrimBox ⊆ BleedBox ⊆ MediaBox, per PDF/X spec. RIPs and proofers use these boxes to identify the live area without guessing.

Element coordinates in the JSON stay relative to the trim corner — a (0, 0) element still lands at the top-left of the trim. Backgrounds extend automatically into the bleed strip; the crop-mark margin remains unprinted.

DPI handling

Coordinates in the JSON are pixels at the specified DPI; PDFs use points (1pt = 1/72 inch). The library converts: points = pixels × (72 / dpi).

// uses dpi from JSON (or 72 if unspecified)
await jsonToPDF(data, './output.pdf');

// override
await jsonToPDF(data, './output.pdf', { dpi: 150 });

A 1920×1080 canvas at 300 DPI exports as 6.4″ × 3.6″; the same canvas at 72 DPI exports as 26.67″ × 15″.

PDF/X-1a

Print-ready output with CMYK conversion, transparency flattening, and font outlining.

await jsonToPDF(data, './print-ready.pdf', {
  pdfx1a: true,
  validate: true, // optional — verify PDF/X-1a compliance
  metadata: {
    title: 'Catalog Cover',
    author: 'Marketing Team',
    application: 'Polotno Automation 1.0',
  },
});

Note: PDF/X-1a conversion requires GhostScript on the host machine — brew install ghostscript, apt-get install ghostscript, or download from ghostscript.com.

Spot colors and overprint

Map specific fills or strokes to separation inks for foil, Pantone, or varnish workflows. Any element using the matched color is exported with the correct separation ink; CMYK fallbacks ensure predictable previews.

await jsonToPDF(data, './foil-cover.pdf', {
  pdfx1a: true,
  spotColors: {
    'rgba(255,215,0,1)': {
      name: 'Gold Foil',
      pantoneCode: 'Pantone 871 C', // optional reference
      cmyk: [0, 0.15, 0.5, 0],      // 0–1 range, used as fallback
      overprint: true,
    },
    '#C0C0C0': {
      name: 'Silver Foil',
      cmyk: [0, 0, 0, 0.25],
      overprint: true,
    },
  },
});

Color matching is flexible. '#FFD700', '#ffd700', 'rgb(255,215,0)', and 'rgba(255,215,0,1)' all match the same color. Works on text, lines, figures (rect, circle, star, blobs), and SVG elements.

overprint: true tells the press to print the spot ink on top of the underlying CMYK rather than knocking it out. Without overprint, a misregistered foil die leaves a visible white halo at the edge. With overprint, CMYK prints continuously through the spot region and the foil stamps over it. This is the standard choice for foil and varnish.

Tip: Verify spot colors in Adobe Acrobat Pro: Tools → Print Production → Output Preview → Separations. Use Simulate Overprinting to preview how the press will composite the layers.

Caveat: Spot color preservation through PDF/X-1a depends on Ghostscript not flattening transparency in the spot region. Plain figures, lines, text, and simple SVG paths work. SVGs that use <clipPath> or <mask> may have their spot color flattened to CMYK during pdfx1a conversion. For foil regions, prefer plain shapes or simple SVG paths over masked artwork.

Full reference

For all options and the latest changes, see the @polotno/pdf-export README on npm.


Troubleshooting

Bleed not visible on canvas? Use store.toggleBleed(true).

Raster export looks low quality? Increase pixelRatio to 2 or 4. dpi controls page dimensions, not quality.

Wrong page size? Adjust the JSON dpi value (or pass dpi to jsonToPDF).

Spot color rendered as CMYK in the foil region? Check whether the artwork uses <clipPath> or <mask> — Ghostscript may flatten transparency groups during PDF/X-1a conversion. Replace with plain shapes or simple paths.

On this page