Conversion in Polotno goes through the design schema rather than through a rasteriser. The PDF is parsed into typed elements first, then written out in the target format. That intermediate step is why the output keeps its layout, why text survives as text, and why you can change the document before converting it.
The conversion path
Every conversion is the same two moves: parse to JSON, write to a format.
import { pdfToJson } from '@polotno/pdf-import';
import { createStore } from 'polotno/model/store';
const json = await pdfToJson({ pdf: await file.arrayBuffer() });
const store = createStore({ key: 'YOUR_KEY' });
store.loadJSON(json);
await store.waitLoading();
await store.saveAsImage({ fileName: 'page.png' }); // raster
await store.saveAsSVG({ fileName: 'page.svg' }); // vector
await store.saveAsHTML({ fileName: 'page.html' }); // self-contained page
// back to PDF: jsonToPDFBlob() for vector, store.saveAsPDF() for rasterBecause the parse and the write are separate, you can inspect or modify the design in between — which is the difference between a converter and a pipeline.
Supported targets
| Target | Output | Live tool |
|---|---|---|
| PNG | Lossless raster at the page's native resolution | PDF to PNG |
| JPG | Photographic raster, smaller files | PDF to JPG |
| SVG | Vector, one file per page | PDF to SVG |
| HTML | Single self-contained file, inline SVG, assets embedded | PDF to HTML |
| PPTX | Editable slides | PDF to PPTX |
| JSON | Typed elements in the Polotno schema | PDF to JSON |
Conversion also works in the other direction: SVG to PDF, PSD to PDF, and AI to PDF.
Each tool page runs the conversion client-side, so you can test the fidelity on your own documents before writing any integration code.
Structured data extraction
Converting to JSON gives layout-aware structured data rather than a flat text dump. Each element carries its type, position, font, colour, and page.
That distinction matters in two places. For LLM ingestion, spatial context improves layout-sensitive tasks — contract review, quote extraction, understanding which label belongs to which value. For automated pipelines, explicit coordinates make edits addressable: find the element, change it, re-render.
const json = await pdfToJson({ pdf: buffer });
const textRuns = json.pages.flatMap((page) =>
page.children.filter((el) => el.type === 'text')
);This is not an invoice parser and not a table-extraction engine. It returns the document's structure, not a semantic interpretation of it.
Where conversion runs
Client-side conversion keeps the file on the user's machine, which is usually the right default — people convert invoices, contracts, payslips, and statements. Nothing is uploaded, nothing is queued, and encrypted files are unlocked locally.
Server-side conversion suits batch work and deterministic output. The same functions run under Node, and the Cloud Render API handles the render leg if you would rather not operate a fleet.
Limits worth knowing
- Scanned PDFs have no text layer. Conversion to JSON returns image elements only. OCR must happen before import, using a dedicated tool.
- JPG softens text. Use PNG for type-heavy pages; JPG's compression is built for photographs.
- Compression is not conversion. Re-rendering a PDF through the schema is not a file-size optimisation pass, and should not be treated as one.
Related reading
- PDF import docs: the parser API.
- Import and export overview: every supported format.
- PDF editing: change the document before converting it.
