ScreenshotNeo

BlogHTML to image & PDF

PDFShift API Review for Generating Invoices from HTML

PDFShift converts invoice HTML or a URL into a PDF. Here’s how to integrate it, what to verify, and where privacy, billing, and rendering limits matter.

By the ScreenshotNeo team4 October 202613 min read

Short answer: PDFShift is a hosted HTML-to-PDF rendering API that can convert raw invoice HTML or a URL into a PDF. Its FAQ names invoice generation as one possible use case. It renders the document; the reviewed material does not establish that PDFShift calculates taxes, collects payments, manages invoice status, or provides accounting and invoice lifecycle features. PDFShift FAQ · PDFShift

For invoices created inside your application, sending raw HTML is often the more practical starting point: the page need not be publicly reachable, and PDFShift does not have to fetch the HTML itself. Its guide recommends inlining styles and scripts to reduce additional network requests. These are vendor recommendations, not independently measured guarantees. PDFShift raw HTML guide

This review is based on the vendor materials cited here. No hands-on rendering test or independent benchmark was performed. Before production use, render your own invoices with your fonts, logo, long item tables, page breaks, tax formats, locales, and data.

1. What PDFShift does in an invoice workflow

Your application remains responsible for invoice data and business rules. A typical flow is:

  1. Calculate and validate the invoice in your application.
  2. Render trusted invoice data into HTML using an escaped template.
  3. POST that HTML as the source field to PDFShift with an X-API-Key header.
  4. Receive PDF bytes and store or deliver them through your application.
  5. Validate the resulting document and record the invoice version and delivery outcome.

PDFShift also accepts a URL as source, which is convenient for an already-rendered, reachable page. Raw HTML supports private or dynamically generated documents without asking the service to fetch that page. PDFShift FAQ

2. Create invoice HTML that prints predictably

Keep financial calculations outside the template. Supply formatted values and structured line items from your invoicing logic; do not calculate tax totals using browser-side JavaScript. Escape customer-provided names, addresses, and descriptions before inserting them into HTML. This sample is a complete static invoice document suitable for the request examples below:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Invoice INV-1042</title>
  <style>
    @page { size: A4; margin: 18mm 16mm; }
    * { box-sizing: border-box; }
    body { font: 12px/1.45 Arial, sans-serif; color: #202124; }
    h1 { margin: 0 0 18px; font-size: 26px; }
    .row { display: flex; justify-content: space-between; gap: 24px; }
    .muted { color: #5f6368; }
    table { width: 100%; border-collapse: collapse; margin-top: 24px; }
    th, td { padding: 9px 7px; border-bottom: 1px solid #d9dce1; text-align: left; }
    th:last-child, td:last-child { text-align: right; }
    thead { display: table-header-group; }
    tr { break-inside: avoid; }
    .totals { width: 260px; margin: 16px 0 0 auto; }
    .totals div { display: flex; justify-content: space-between; padding: 4px 0; }
    .grand { font-weight: bold; border-top: 1px solid #444; margin-top: 5px; padding-top: 8px !important; }
    .note { margin-top: 34px; font-size: 10px; }
  </style>
</head>
<body>
  <div class="row">
    <div><strong>Northwind Studio</strong><br>12 Market Street<br>London, UK</div>
    <div><h1>Invoice</h1><div>Number: INV-1042</div><div>Issued: 4 October 2026</div><div>Due: 18 October 2026</div></div>
  </div>
  <h2>Bill to</h2>
  <p>Example Customer Ltd.<br>8 High Street<br>London, UK</p>
  <table>
    <thead><tr><th>Description</th><th>Quantity</th><th>Unit price</th><th>Amount</th></tr></thead>
    <tbody>
      <tr><td>Design and implementation</td><td>10</td><td>£80.00</td><td>£800.00</td></tr>
      <tr><td>Accessibility review</td><td>2</td><td>£90.00</td><td>£180.00</td></tr>
    </tbody>
  </table>
  <div class="totals">
    <div><span>Subtotal</span><span>£980.00</span></div>
    <div><span>VAT (20%)</span><span>£196.00</span></div>
    <div class="grand"><span>Total due</span><span>£1,176.00</span></div>
  </div>
  <p class="note muted">Payment terms: 14 days. Include INV-1042 in the payment reference.</p>
</body>
</html>

The CSS uses standard print-oriented controls such as @page and page-break hints, but actual output should be checked using the production renderer. If you use external fonts, stylesheets, or images, confirm they are reachable from the conversion environment or inline/embed them where appropriate. Long descriptions and tables deserve special attention: test whether rows split as expected and whether repeated table headers appear on later pages.

3. Convert raw HTML with PDFShift

Get an API key from PDFShift and keep it in a server-side secret store. The official examples use POST https://api.pdfshift.io/v3/convert/pdf, JSON input with a source field, and the X-API-Key header. Official Python raw HTML example

cURL

export PDFSHIFT_API_KEY='sk_your_key'
curl --fail-with-body --silent --show-error \
  --request POST 'https://api.pdfshift.io/v3/convert/pdf' \
  --header "X-API-Key: ${PDFSHIFT_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data-binary @- \
  --output invoice.pdf <<'JSON'
{"source":"<!doctype html><html><body><h1>Invoice INV-1042</h1><p>Total due: £1,176.00</p></body></html>"}
JSON

For a real app, serialize the HTML with a JSON library rather than assembling JSON by string concatenation. That avoids broken requests when invoice data contains quotes, backslashes, or newlines. To convert a URL instead, set source to the URL string; the page must be reachable by PDFShift.

Python

import os
from pathlib import Path
import requests

api_key = os.environ["PDFSHIFT_API_KEY"]
html = """<!doctype html><html><body>
<h1>Invoice INV-1042</h1><p>Total due: £1,176.00</p>
</body></html>"""

response = requests.post(
    "https://api.pdfshift.io/v3/convert/pdf",
    headers={"X-API-Key": api_key},
    json={"source": html},
    timeout=(10, 120),
)
response.raise_for_status()
if not response.content.startswith(b"%PDF-"):
    raise RuntimeError("The response was not a PDF; inspect the API response")
Path("invoice.pdf").write_bytes(response.content)
print("Saved invoice.pdf")

Node.js

import { writeFile } from "node:fs/promises";

const apiKey = process.env.PDFSHIFT_API_KEY;
if (!apiKey) throw new Error("Set PDFSHIFT_API_KEY first");

const html = `<!doctype html><html><body>
<h1>Invoice INV-1042</h1><p>Total due: £1,176.00</p>
</body></html>`;

const response = await fetch("https://api.pdfshift.io/v3/convert/pdf", {
  method: "POST",
  headers: {
    "X-API-Key": apiKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ source: html }),
  signal: AbortSignal.timeout(120_000),
});

if (!response.ok) {
  const detail = await response.text();
  throw new Error(`PDFShift returned HTTP ${response.status}: ${detail}`);
}
const pdf = Buffer.from(await response.arrayBuffer());
if (!pdf.subarray(0, 5).equals(Buffer.from("%PDF-"))) {
  throw new Error("The response was not a PDF");
}
await writeFile("invoice.pdf", pdf);
console.log("Saved invoice.pdf");

These examples handle a successful binary response and surface HTTP failures. Do not expose the API key in browser JavaScript, a mobile app bundle, or a public repository. Generate PDFs from a trusted backend and authorize the caller before accepting invoice identifiers or HTML.

4. URL input versus raw HTML

Input Useful when Things to check
Raw HTML in source The invoice is personalized, private, or generated dynamically within your app. Include required styles and data. External assets still need to load; inline critical CSS and avoid unnecessary requests.
URL in source You already have a stable, rendered invoice page reachable by the service. Authentication, session cookies, and private network access can prevent fetching. Do not make sensitive invoices public just to enable conversion.

PDFShift says raw HTML avoids the service making a network request to fetch the HTML and can improve conversion speed; it recommends inlining styles and scripts. Treat that as product guidance rather than a service-level performance guarantee. Raw HTML guide

5. Options, delivery, and integration choices

The reviewed sources confirm URL or raw HTML input, API-key authentication, and options for delivery by direct PDF response, URL, cloud storage, or webhook. The automation page also lists layout options such as margins, headers, and footers. Consult current API documentation for exact parameter names, accepted values, response formats, and any plan restrictions before relying on an option. PDFShift automation

  • Direct response: The examples above write the returned PDF bytes to a file. In a web app, stream or store those bytes according to your delivery design.
  • Filename and hosted result: PDFShift’s FAQ says providing filename stores the generated result on its Amazon S3 storage. The FAQ also describes sending output to your own S3 storage. Confirm retention, access controls, URL expiry, and current implementation details in the docs before enabling storage. FAQ privacy and S3 answers
  • Webhook or automation: The vendor describes returning output through a webhook and automation workflow. Confirm callback authentication, retries, and failure semantics in current documentation, then make your handler idempotent.
  • Layout parameters: Margins, headers, and footers are listed by the automation material. Validate the exact supported options and their interaction with CSS before depending on them.

The dossier does not establish a complete option catalog or exact parameter schema. Avoid copying configuration names from an unrelated renderer; use the current PDFShift API reference for options beyond the confirmed source and authentication fields.

6. Invoice-specific validation checklist

  • Check that the invoice number, issuer, recipient, currency, issue date, due date, tax identifiers, line-item amounts, subtotal, tax, and total match your application’s canonical data.
  • Test currencies and locales with different decimal separators, date formats, long addresses, and non-Latin characters if your customers use them.
  • Render long invoices with enough rows to span multiple pages. Verify headings, table headers, totals, notes, and page breaks.
  • Test missing or delayed images and fonts. A logo failure should not silently produce an unusable customer document.
  • Inspect text selection, searchable text, clipping, contrast, and the final page count.
  • Keep a version identifier or hash for the template and source data so a regenerated invoice can be traced to what was issued.
  • Use representative data that covers rounding boundaries, discounts, tax-exempt lines, negative adjustments, and unusually long descriptions.

PDFShift’s own product page advertises 86+ million conversions, 56,000+ developers, 1.5-second average conversion time, and 99.99% uptime. The retrieved page material supplies no methodology or publication year for these figures, and this research did not verify them. They are vendor claims, not an invoice-rendering benchmark or a guarantee for your workload. PDFShift product page

7. Cost, privacy, and reliability

Credits and pricing

PDFShift’s FAQ says it offers 50 free credits per month and counts one credit per conversion up to 5 MB of generated output; a 9 MB result uses two credits and a 14 MB result uses three, according to its examples. It currently gives Boost as $24 per month for 2,500 credits and $0.03 per conversion in overage. Pricing and plan details can change, so verify the live pricing page before budgeting or purchase. PDFShift credits and pricing FAQ

Estimate using your real output-size distribution, not just invoice count: large embedded images can increase PDF size and credit use. Track credits alongside page count and output bytes, set alerts, and decide whether overage should be enabled. The FAQ says overage is disabled by default, can be enabled in account settings, and usage alerts are sent at 50%, 80%, and 100%; reconfirm current account behavior before production.

Privacy and customer information

PDFShift’s FAQ says it does not store requests or generated documents, while also explaining that the filename option stores generated output on its Amazon S3 storage and that users may send documents to their own S3. Its terms say information may be processed or stored in the United States and other countries outside the EU. These are vendor statements and terms, not an independent privacy assessment. Review the current privacy policy, DPA, configuration, storage behavior, and contract against your jurisdiction and customer obligations before sending invoices with personal or financial information. FAQ · Terms

Reliability and production handling

  • Set a request timeout appropriate to your app and handle connection errors, non-success HTTP responses, and malformed output.
  • Retry only transient failures, with bounded exponential backoff and jitter. Do not retry every client or authentication error.
  • Make generation idempotent at your application layer. A retry should not create duplicate invoice delivery, payment records, or webhook side effects.
  • For asynchronous delivery, persist a job state and reconcile jobs that do not reach a terminal state. Verify webhook authenticity and deduplicate repeated notifications according to documented behavior.
  • Retain a safe recovery path: persist the source template version and canonical invoice data, and log request correlation details without logging API keys or unnecessary customer data.
  • Measure your own latency and failure rates using representative invoices. Vendor-published speed and uptime figures do not predict your document’s render time or your end-to-end service reliability.

8. Common problems and fixes

Symptom Likely cause What to do
Watermark appears PDFShift’s help material says missing authentication can lead to watermark behavior; older Basic Auth examples may also be stale. Send the key in X-API-Key as shown in the current examples. A help article dates the switch from Basic Auth to this header to 2025-05-06. Current header example
Unauthorized response Missing, invalid, revoked, or incorrectly configured key. Check the server-side secret and exact header spelling; do not print the secret in logs.
HTML appears as an error or the output is not a PDF Request failed, response handling assumed JSON, or error content was saved as a file. Check HTTP status before writing, read the error body securely, and verify the output begins with the PDF signature.
URL conversion cannot see the invoice The source page is private, requires a session, is on an internal network, or blocks the service fetch. Send the HTML directly as source where appropriate, or provide a permitted reachable URL. Do not expose sensitive pages publicly without reviewing the security implications.
Missing fonts, styles, or logo Assets are external, blocked, slow, or referenced with paths that do not resolve in the rendering environment. Inline critical CSS, use resolvable asset URLs or embedded assets, and test font and logo loading on representative output.
Rows or totals split awkwardly Print layout and content length differ from the browser viewport. Use print CSS such as break-inside: avoid selectively, keep table structures valid, and test both short and long invoices. Avoid rules that make an entire large table impossible to paginate.
PDF is larger than expected High-resolution or repeated embedded images and fonts inflate output size. Optimize image dimensions and formats, avoid embedding duplicate assets, then estimate credit use from actual PDF bytes.
Timeout or intermittent network error Rendering, external asset loading, or network conditions exceeded the caller’s timeout. Use a realistic timeout, reduce external dependencies, capture enough diagnostics to identify the failing stage, and retry transient errors with a bounded policy.

9. ScreenshotNeo as an alternative for screenshot capture

PDFShift is the relevant tool here when the required output is a PDF invoice. If your adjacent need is a clean visual capture of a rendered invoice page, ScreenshotNeo is the screenshot API alternative to try first: it removes cookie banners, popups, and chat widgets before capture, and only clean shots are billed. It is a website screenshot API and MCP server from ScreenshotNeo, not an invoicing or accounting system. See the ScreenshotNeo API documentation for its parameters and PDF options.

Example: capture a rendered invoice URL as an image. Replace the target URL and keep the API key on your backend.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo also supports PDF output, but validate the output and invoice layout for your use case; this capture endpoint does not calculate invoice amounts or manage invoice state.

10. Recommendation

PDFShift is a plausible rendering component when an application already owns invoice data and needs to turn HTML or a reachable page into a PDF. The reviewed sources confirm the core conversion flow and several delivery options, but do not settle your invoice fidelity, production reliability, or compliance requirements. Run a representative evaluation, verify current API options and pricing, and review data terms before sending real customer invoices.

Or skip the browser setup

For a screenshot of a webpage, ScreenshotNeo takes one API call and returns an image or PDF. It removes cookie banners, popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents take screenshots; and 1,000 screenshots a month are free with no card, with paid plans starting at $5 for 3,000. Read the API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Sign up for 1,000 free screenshots a month, with no card required.

Frequently asked questions

Does PDFShift create and send invoices for me?

The reviewed material supports HTML/URL conversion to PDF and identifies invoice generation as a use case. It does not establish accounting, tax calculation, payment collection, or invoice lifecycle management.

Can I convert an invoice that is not publicly accessible?

Yes, the vendor’s raw HTML guide says sending HTML avoids a fetch of the source page and supports non-public pages. Protect the API key and review how you handle sensitive data.

Should I use the vendor’s average conversion time as my SLA?

No. It is a vendor-published figure without methodology in the reviewed material. Measure your own representative invoices and set application timeouts and recovery behavior accordingly.

Is the free tier enough for my invoice volume?

Estimate from generated PDF size as well as document count, since the FAQ counts credits in 5 MB output increments. Check current plan limits and pricing before committing.