Skip to content

§ Vue to PDF

Vue to PDF: Convert a Vue Component or HTML to a Real PDF

Turn a Vue component, a rendered page, or raw HTML into a pixel perfect PDF with one API call. Managed Chromium renders your real markup, so text stays selectable and your Tailwind, scoped styles and web fonts survive, no vue-html2pdf screenshot and no browser to run yourself. Try it on any URL below.

  • Early access, launching soon
  • No card required
  • Your HTML stays yours

§ Live demo

Runs in your browser. Nothing is uploaded.

Your PDF is downloading. Want this as one API call, with the page archived too?

§ Short answer

The dependable way to convert Vue to PDF in production is to render your real Vue output in a browser on the server, not to screenshot the DOM in the client. Client libraries like vue-html2pdf and html2pdf.js paint the component onto a canvas and embed that image, so the text is not selectable, it pixelates when zoomed, tall content reflows, and Tailwind v4 oklch() colors break the capture. Sitepdf renders the same HTML your Vue app produces in managed Chromium and returns a true, searchable vector PDF, plus an optional timestamped archive of exactly what was rendered.

Last updated July 2026. Written and fact checked by the Sitepdf team.

§ 00

Three ways to get a PDF out of Vue, compared

Vue has no built in PDF export, so every team picks one of these three routes. They differ most in whether the PDF contains real text and whether your component CSS actually applies.

Approach How it works Output Modern CSS and Tailwind v4 Best for
vue-html2pdf, html2pdf.js
client side
Snapshots a Vue element in the browser and drops the image into a PDF Raster image, text not selectable, pixelates on zoom, content reflows Breaks: oklch() colors throw, gradients and shadows drift A quick client export of one simple, static screen
jsPDF by hand You place text and boxes onto the page yourself in code True vector PDF No: you rebuild the layout, your component CSS does not apply A short fixed layout you are willing to lay out manually
Server side Chromium API
Sitepdf
Renders your real page or HTML in a managed browser True searchable vector PDF, print accurate Full support, it is a real current browser Production documents, identical output for every user, a dated record

The honest read: jsPDF is genuinely fine when the document is short and you are happy to position each element in code, and it costs nothing. If instead you want the PDF to look like the Vue page your users already see, a real browser has to do the rendering, which is why the client screenshot route keeps disappointing teams once fonts, charts and Tailwind enter the picture.

§ 01

Why vue-html2pdf keeps letting teams down

The usual first attempt is vue-html2pdf, which is a thin Vue wrapper around html2pdf.js, which itself chains html2canvas and jsPDF. It is appealing because it runs entirely in the browser and needs no backend. It also quietly produces a worse document than people expect. Under the hood it paints the component onto a canvas and embeds that canvas as an image, so the PDF is a picture of your UI. The text inside cannot be selected, copied or searched, it turns fuzzy the moment someone zooms in, and because html2pdf.js resizes the root element to fit a page, the internal content reflows and long reports get sliced awkwardly across pages.

Then there is the CSS problem that arrived with Tailwind v4. Tailwind now emits colors with the oklch() function, and html2canvas cannot parse it, so the capture fails with "Attempting to parse an unsupported color function oklch". You can patch it by overriding every color at render time, but that is a maintenance tax you pay forever. A real browser has none of these limits, because it is the same engine that drew the page in the first place.

§ 02

The server-side path: render your real Vue output, keep real text

The fix is to move rendering off the client and into a real browser. You have two clean ways to feed Sitepdf. If the document is a live route in your app, an invoice page, an order confirmation, a dashboard export, point the API at that URL and it loads the page in managed Chromium exactly as a visitor would, runs your JavaScript, waits for your charts, and returns the PDF. If you would rather not expose a route, render the component to an HTML string on the server with renderToString from @vue/server-renderer and post that HTML instead.

import { createSSRApp } from "vue";
import { renderToString } from "@vue/server-renderer";
import Invoice from "./Invoice.vue";

const app = createSSRApp(Invoice, { invoice });
const html = await renderToString(app);

const res = await fetch("https://api.sitepdf.com/v1/render", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.SITEPDF_KEY}` },
  body: new URLSearchParams({ html, format: "Letter", archive: "true" }),
});
const { pdf_url } = await res.json();

Either way the browser does the layout, so your Tailwind classes, scoped styles, CSS grid, web fonts and background colors all render the way they do on screen, and the resulting text is real, selectable and searchable. One thing to watch when you render to a string: renderToString gives you markup, not your bundled CSS, so inline the styles or link your stylesheet in the HTML you post. Our HTML to PDF in Node.js guide covers the same call from an Express or Nuxt server route, and the PDF generator API page has the full parameter list.

§ 03

When jsPDF on its own is the better choice

We are not going to pretend the API is always the answer. If your PDF is a short, fixed document that looks nothing like any page in your app, a shipping label, a ticket, a one page certificate, then plain jsPDF is a reasonable fit and it costs nothing. You position the text and boxes yourself, and because it never touches a browser it is fast and has no infrastructure. The catch is exactly that: it ignores your component CSS, so you are rebuilding the layout by hand, and anything with real typography, tables or responsive design becomes tedious to express in coordinates.

So the rule is simple. Building a brand new, short document layout from scratch, with no HTML worth reusing? jsPDF earns its place. Reusing a Vue page or template your users already see, and you want the PDF to match it? Render it in a real browser. The screenshot wrappers are the one option that rarely wins on a document that matters, because they trade away real text for convenience.

§ 04

Keep a dated copy of what you generated

There is one thing no Vue library gives you, on the client or the server: a record. When you generate an invoice, a receipt or a signed quote, the file goes to the customer and nothing verifiable stays with you. Add archive=true to the render call and Sitepdf also stores a timestamped, immutable snapshot of exactly what it rendered, retrievable by id later. For finance, legal and compliance work that provenance is often the reason to render server side in the first place. The website archiving page explains how the record works, and the React to PDF and Angular to PDF pages walk the same trade offs for the other big component frameworks. Renders are transient by default; leave archiving off and we return the PDF and store nothing.

Point the API at a rendered Vue route, or post HTML you rendered on the server.
curl https://api.sitepdf.com/v1/render \
  -H "Authorization: Bearer $SITEPDF_KEY" \
  -F url=https://app.example.com/invoices/8842 \
  -F format=Letter \
  -F wait_for="#invoice-total" \
  -F archive=true

{
  "pdf_url": "https://api.sitepdf.com/v1/documents/doc_7v1qm.pdf",
  "pages": 2,
  "rendered_in_ms": 1690,
  "archive": {
    "id": "arc_m41td",
    "captured_at": "2026-07-19T18:41:07Z",
    "retrieve_url": "https://api.sitepdf.com/v1/archives/arc_m41td"
  }
}

The API is in early access; this is the documented call shape it opens with. Full request and response walkthrough.

§ 05

Questions about this job

How do I convert a Vue component to PDF?
Render the component to HTML on the server with renderToString from @vue/server-renderer, or point a rendering API at the live route that shows it. A real browser then converts that HTML to a PDF, so the text stays selectable and your CSS applies. Avoid client-side vue-html2pdf snapshots for anything important, because they embed an image, not real text.
Why is my vue-html2pdf output blurry or not selectable?
Because vue-html2pdf wraps html2pdf.js, which screenshots the DOM with html2canvas and places that image in the PDF. An image has no real text to select and it pixelates when zoomed. To get a crisp, searchable PDF you need a browser to render the page to PDF directly, which is what a server-side Chromium API does.
Does html2pdf.js work with Tailwind v4 in Vue?
Not out of the box. Tailwind v4 emits colors with the CSS oklch() function, and the html2canvas step inside html2pdf.js cannot parse it, so the capture throws an unsupported color function error. You can override colors at render time as a workaround, or render server side in a real browser, which supports oklch natively and needs no patching.
How do I generate a PDF from Vue on the server?
Use renderToString from @vue/server-renderer to turn the component into an HTML string, inline or link its CSS, then post that HTML to a rendering API that runs managed Chromium. You get back a true vector PDF with selectable text and full modern CSS support, and nothing runs a browser inside your own server process.
Does this work with Nuxt?
Yes. In a Nuxt server route or Nitro handler you either post the HTML you rendered with renderToString, or pass the URL of a rendered Nuxt page, to the render endpoint and stream back the PDF. Because no browser launches inside your function, it also works on the serverless targets Nuxt commonly deploys to, where you cannot start Chromium yourself.

§ Early access

Get on the early-access list

The API opens to the list first, in order. Early access locks the planned launch rates for 12 months. No card required, launching soon.

Render + archive, one API