jsPDF is excellent for lightweight browser exports
jsPDF is popular because it solves a real product problem: create a PDF inside the browser without running a backend service. A developer can draw text, lines, images, and simple tables, then trigger a download from the same page. For prototypes, small admin screens, local receipts, and offline PWAs, that is a strong fit.
The product question is where that browser boundary stops being the right one. Once the PDF becomes a business document that customers scan, archive, email, or submit to another system, the work is no longer just “draw a file.” It becomes font management, barcode accuracy, mobile stability, deterministic output, and sometimes PDF/A or e-invoice packaging.
Same PDF output, different product boundary
With jsPDF, your frontend application is the renderer. Every browser tab has to hold the library, any custom fonts, intermediate images, barcode output, and the final PDF bytes. That keeps the library bill at zero, but moves the production responsibility onto each user device.
With gPdf, the browser or backend sends a structured DocumentRequest or template_id + data request. gPdf owns the render environment, bundled fonts, barcode geometry, and binary PDF generation at the edge. The application stays responsible for the data and template logic, not the PDF engine.
Product fit: offline export vs operational documents
Choose jsPDF when the PDF is a local convenience feature: a small export button, a simple Latin-only receipt, a dashboard snapshot, or a PWA that must keep working with no network connection.
Choose gPdf when the PDF is part of an operational workflow: shipping labels, warehouse tags, invoices, tickets, statements, customs forms, and cross-border receipts. Those documents need the same output across devices, not whatever the current browser tab can safely assemble.
Cost model: free library vs owned production surface
The jsPDF library has the obvious price advantage: the library itself is open source, and browser CPU is not a line item on your cloud bill. For a small internal feature, that can be the cheapest path.
The production cost appears in the work around the library:
- CJK-capable font files or generated base64 font modules.
- Barcode encoding and conversion libraries.
- Browser-specific memory and download bugs.
- Print QA for scanners and thermal printers.
- Regression tests across desktop, iOS Safari, Android WebView, and embedded browsers.
gPdf turns that into a usage bill. The public Basic plan starts at 5/month for 100K pages, with standard overage starting at 0.00005/page. That is a vendor cost, but it removes the need to make every frontend bundle and every user device behave like a production PDF service.
The CJK cost is not just file size
The first hard edge is CJK text: Chinese, Japanese, and Korean.
jsPDF’s built-in standard PDF fonts are useful for simple Latin output, but they do not cover every Unicode glyph. When the document contains CJK text, the application needs a font that actually contains those glyphs. In practice, browser-side implementations often package a TTF file, convert it into a base64 JavaScript module, or fetch font data before generating the PDF.
That cost is paid twice: first as a larger frontend payload, then again as browser memory while the PDF is being generated. On mobile, the same tab may hold the web app, the font, barcode buffers, images, and final PDF bytes at the same time.
gPdf keeps that work server-side. The browser sends structured JSON; the renderer chooses from bundled fonts that cover Latin, Greek, Cyrillic, CJK, Arabic, Devanagari, Bengali, Thai, and monospace text. A 2 KB order payload does not need to become a 12 MB font delivery path.
Barcode cost: encoding is easy, print reliability is harder
For logistics, ecommerce, manufacturing, healthcare, ticketing, and retail workflows, the barcode can be more important than the visible copy. A human reads the order number; the operation reads Code 128, GS1-128, QR, DataMatrix, or PDF417.
With jsPDF, barcode generation is usually a separate product decision. Teams combine jsPDF with another encoder, render the barcode into SVG, canvas, or an image, then place that result into the PDF. That works for a coupon QR code or a proof of concept.
It becomes fragile when the printed barcode is operationally critical:
- A canvas barcode may be rasterized at the wrong resolution.
- A scaled image can blur bars, modules, or quiet zones.
- A browser, CSS transform, or export path can change the final physical size.
- Different barcode formats may need different libraries or conversion paths.
- Thermal printers at 203 DPI expose small sizing mistakes quickly.
gPdf treats barcodes as document elements. The request says type: "barcode", the format, the payload, and the physical size in millimetres. The renderer emits vector barcode geometry inside the PDF for supported 1D and 2D formats, so text, shapes, tables, images, and barcodes stay in one coordinate system.
Studio and template iteration
jsPDF is code-first. A layout change usually means editing drawing commands, positions, font registration, image conversion, and barcode placement in JavaScript.
gPdf supports the same API-first workflow, but adds gPdf Studio as a free visual designer for the PDF layout. Teams can add and drag text, images, tables, shapes, headers, footers, and barcodes, then connect the design to template_id + data generation. That matters when a label, invoice, or receipt format changes often and non-PDF-specialists need to participate in the layout.
Mobile browsers are the wrong place for heavy PDF work
Client-side PDF generation sounds cheap because the server bill is zero. The cost moves to the user device.
On desktop, that may be fine. On mobile browsers, a production document can push the tab hard: CJK font data, base64 images, canvas buffers, barcode images, generated PDF bytes, and the running application all compete for memory at the same time. iOS Safari and low-memory Android devices are less forgiving than a developer laptop.
Moving generation to gPdf changes the shape of the problem. The browser builds a small JSON request, waits for a binary response, and downloads the finished PDF. The user’s tab no longer has to be the font manager, barcode renderer, layout engine, and binary PDF writer.
When jsPDF is still the right choice
There are strong reasons to keep jsPDF.
If the user must export while offline, jsPDF is the better fit. If the data cannot leave the device at all, browser-side generation is the cleaner privacy boundary. If the document is small, Latin-only, and used occasionally, the operational cost of introducing an API may not be worth it. For prototypes and internal tools, jsPDF is often exactly the fastest path.
The decision changes when the output is part of an operational workflow: a shipping label that must scan, an invoice that must archive, a ticket that must verify, or a cross-border order document that must render CJK names correctly. At that point, “generate a PDF in the browser” becomes less important than “generate the same production PDF reliably.”
Migration shape
The migration is not “replace one function call.” It is moving from imperative browser drawing to a structured document request.
- // Before: browser-side drawing with jsPDF plus extra font/barcode setup.
- import { jsPDF } from "jspdf";
- import JsBarcode from "jsbarcode";
-
- const doc = new jsPDF({ unit: "mm", format: [100, 150] });
- // Load a CJK-capable TTF and register it before drawing CJK text.
- doc.addFileToVFS("NotoSansCJK-Regular.ttf", base64Font);
- doc.addFont("NotoSansCJK-Regular.ttf", "NotoSansCJK", "normal");
- doc.setFont("NotoSansCJK");
- doc.text("跨境订单 / Cross-border order", 6, 10);
-
- // Generate a barcode separately, then place it into the PDF.
- JsBarcode(canvas, "PDN0003507278", { format: "CODE128" });
- doc.addImage(canvas.toDataURL("image/png"), "PNG", 6, 72, 72, 20);
- doc.save("label.pdf");
+
+ // After: send one structured DocumentRequest to gPdf.
+ const res = await fetch("https://api.gpdf.com/api/v1/pdf/render", {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${KEY}`,
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ settings: {
+ defaults: {
+ text: {
+ font_family: "NotoSans-Regular",
+ font_mode: "prefer",
+ font_size: 9,
+ color: "#111827"
+ }
+ }
+ },
+ pages: [{
+ width: 100,
+ height: 150,
+ elements: [
+ {
+ type: "text",
+ x: 6,
+ y: 8,
+ content: "跨境订单 / Cross-border order",
+ style: { width: 88, font_size: 12, font_weight: "bold" }
+ },
+ {
+ type: "barcode",
+ x: 6,
+ y: 70,
+ width: 72,
+ height: 18,
+ format: "code128",
+ content: "PDN0003507278",
+ barcode_text: { enabled: true, position: "bottom", offset: 1 }
+ },
+ {
+ type: "barcode",
+ x: 80,
+ y: 8,
+ width: 14,
+ height: 14,
+ format: "qrcode",
+ content: "https://track.example/PDN0003507278",
+ barcode_text: { enabled: false, position: "bottom" }
+ }
+ ]
+ }]
+ })
+ });
+ const pdf = await res.arrayBuffer();
The important shift is ownership. With jsPDF, your web app owns the CJK font path, barcode generation path, browser memory profile, and export behaviour. With gPdf, your application owns the data and template; the edge renderer owns the document mechanics.
Related PDF generation scenarios
Teams comparing jsPDF and gPdf often also search for CJK PDF generation, browser PDF generation alternatives, barcode PDF APIs, mobile-safe PDF generation, offline PDF export, JSON to PDF API, invoice PDF generation, ticket PDF generation, shipping label PDF generation, and visual PDF template design.
FAQ
Is jsPDF free?
The library itself is open source. The production cost is the surrounding work: CJK fonts, barcode libraries, browser QA, print QA, and support for devices that run out of memory.
Does gPdf replace every jsPDF use case?
No. Offline browser export and local-only documents are still jsPDF’s natural territory. gPdf is for production documents where a controlled renderer is worth the API call.
Why mention barcode cost separately?
Because a barcode that looks fine on screen can still fail after scaling, rasterization, or thermal printing. Operational documents need scanner reliability, not just a visible pattern.
See also
- The gPdf API reference - DocumentRequest, barcode elements, font fallback, and render endpoints.
- Vector vs raster barcodes in PDFs - why barcode geometry matters after printing.
- GS1-128 barcodes at 0.1 mm precision in JSON - label-oriented barcode sizing details.
- PDF/A and Factur-X explained for engineers - when archival and e-invoice requirements enter the PDF pipeline.