Most PDF tooling treats a document as something to view or annotate on top of. Polotno takes a different route: it parses the PDF into a design schema, so text stays text, images stay images, and vector artwork stays paths. The result is a document your users can genuinely edit on a canvas — then export back out as a vector PDF.
The round trip
Three steps, all available in the browser or on a server.
import { pdfToJson } from '@polotno/pdf-import';
import { jsonToPDFBlob } from '@polotno/pdf-export/browser';
import { createStore } from 'polotno/model/store';
// 1. Parse
const json = await pdfToJson({ pdf: await file.arrayBuffer() });
// 2. Edit — programmatically, or hand the store to the editor UI
const store = createStore({ key: 'YOUR_KEY' });
store.loadJSON(json);
await store.waitLoading();
// 3. Export as vector PDF, with text still selectable
const blob = await jsonToPDFBlob(store.toJSON());Between step two and step three you can do anything the SDK allows: change copy, swap a logo, recolour a background, delete pages, add elements, or apply a template. The editor UI is the same canvas used for images, text, and video, so a user who can edit a social post can edit a PDF.
Try the parse step without writing code in the PDF to JSON tool, which runs the same pdfToJson() function in your browser.
What you get back from a PDF
The parser emits typed elements, not a flattened bitmap:
text— content, font family, size, weight, fill, position, rotation, alignment.image— base64 source, crop region, position, opacity.svg— vector artwork re-emitted as inline SVG with position and size.line— stroke segments with colour, dash, and position.
Because every element carries explicit coordinates, edits are precise and repeatable. The full shape is documented in the PDF import reference and the design schema.
Editing programmatically
The same API that powers the UI is available headlessly, which makes scripted edits straightforward.
// Replace a placeholder across every page
store.pages.forEach((page) => {
page.children
.filter((el) => el.type === 'text' && el.text.includes('{{name}}'))
.forEach((el) => el.set({ text: el.text.replace('{{name}}', customer) }));
});Typical uses: correcting a price across a catalogue, localizing a template, injecting a customer name into a contract draft, or normalizing brand colours across a set of supplied documents.
Export fidelity
There are two export paths, and the difference matters. store.saveAsPDF() is built in and raster — each page is flattened to an image, which is right when you need pixel parity with the canvas. @polotno/pdf-export is vector: text is embedded as subsetted fonts and stays selectable, files are smaller, and output scales for print. Use vector unless you specifically want the flattened version.
Vector export runs in the browser (jsonToPDFBlob) or under Node (jsonToPDF), and supports CMYK, spot colours, bleed, crop marks, and PDF/X-4 or PDF/X-1a — see PDF export.
You are not limited to PDF on the way out. The same edited design exports to PNG, JPG, SVG, HTML, or PPTX.
Honest limits
Worth knowing before you scope a build:
- Scanned PDFs contain no text layer. The parser returns image elements and nothing to edit as text. Run OCR first with a dedicated tool, then import the text-augmented file.
- Form fields are not supported. AcroForm widgets are not parsed as interactive fields.
- Annotations are not supported. There is no comment, highlight, or markup layer.
- Redaction in the security sense is not provided. Deleting an element removes it from the design, which is an editing operation, not a certified redaction.
- Exotic layouts — heavily ligatured scripts, unusual embedded font subsets, and complex transparency groups can shift on re-export. Test with your own documents.
If those limits rule Polotno out, they are genuine reasons to pick a document-processing SDK instead.
Related reading
- PDF import docs: API reference for
pdfToJson(). - PDF conversion: moving PDFs into other formats.
- PDF generation: producing new PDFs from data.
- PDF to JSON tool: run the parser in your browser.
