ScreenshotNeo

BlogHow-to

How to Convert an Indian GST Invoice Webpage to PDF with PDFShift

Convert an Indian GST invoice webpage to PDF with PDFShift. Follow runnable Node.js, cURL, and Python examples, including options for private pages.

By the ScreenshotNeo team4 October 20268 min read

To convert an Indian GST invoice webpage to PDF with PDFShift, send the page URL as source to PDFShift’s PDF conversion endpoint, authenticate with your API key in the X-API-Key header, and save the binary response as a .pdf file. This creates a PDF rendering of the page; it does not validate the invoice or establish that it meets GST requirements.

The examples below use PDFShift’s documented Node.js flow and equivalent cURL and Python requests. See PDFShift’s current documentation for current API details. [c_pdfshift_url]

1. Get the invoice page URL and API key

  1. Copy the URL of the invoice page you want to render. Confirm that it opens in a browser and shows the invoice content you expect.
  2. Get an API key from your PDFShift account. Keep it private; do not commit it to source control or expose it in client-side code.
  3. Decide whether the page is publicly reachable by PDFShift or requires authentication. If it is private, see Private invoice pages.

PDFShift’s URL-to-PDF request uses https://api.pdfshift.io/v3/convert/pdf. The key belongs in the X-API-Key request header. [c_pdfshift_url] PDFShift’s Help Center records that API-key authentication moved to this header on 2025-05-06; check its current docs if you are maintaining an older integration. [c_pdfshift_auth]

2. Convert the invoice webpage to PDF

Use the URL as the request’s source. The endpoint returns PDF bytes; write the response body directly to a file without converting it to text or JSON. [c_pdfshift_url][c_pdfshift_help]

Node.js

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

const apiKey = process.env.PDFSHIFT_API_KEY;
const invoiceUrl = 'https://example.com/invoice/123';

if (!apiKey) {
  throw new Error('Set the PDFSHIFT_API_KEY environment variable.');
}

const response = await fetch('https://api.pdfshift.io/v3/convert/pdf', {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Content-Type': 'application/json',
    'Accept': 'application/pdf',
  },
  body: JSON.stringify({ source: invoiceUrl }),
});

if (!response.ok) {
  const details = await response.text();
  throw new Error(`PDFShift returned HTTP ${response.status}: ${details}`);
}

const pdf = Buffer.from(await response.arrayBuffer());
if (!pdf.subarray(0, 5).equals(Buffer.from('%PDF-'))) {
  throw new Error('The response did not begin with a PDF signature.');
}

await writeFile('invoice.pdf', pdf);
console.log('Saved invoice.pdf');

Run it with PDFSHIFT_API_KEY set in the environment and a URL you are authorized to access. Node.js 18 or later includes the global fetch used here. The PDF signature check catches common cases where an error or unexpected response was saved with a .pdf extension.

cURL

curl --fail-with-body \
  --request POST \
  --url https://api.pdfshift.io/v3/convert/pdf \
  --header "X-API-Key: $PDFSHIFT_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/pdf" \
  --data '{"source":"https://example.com/invoice/123"}' \
  --output invoice.pdf

Set PDFSHIFT_API_KEY in your shell before running the command. --output writes the response body to the named file. --fail-with-body makes HTTP errors visible while retaining the error response body for diagnosis; if your installed cURL is too old to support it, remove that option and check the HTTP status separately.

Python

import os
from pathlib import Path
import requests

api_key = os.environ.get("PDFSHIFT_API_KEY")
if not api_key:
    raise RuntimeError("Set the PDFSHIFT_API_KEY environment variable.")

response = requests.post(
    "https://api.pdfshift.io/v3/convert/pdf",
    headers={
        "X-API-Key": api_key,
        "Accept": "application/pdf",
    },
    json={"source": "https://example.com/invoice/123"},
    timeout=90,
)
response.raise_for_status()

if not response.content.startswith(b"%PDF-"):
    raise RuntimeError("The response did not begin with a PDF signature.")

Path("invoice.pdf").write_bytes(response.content)
print("Saved invoice.pdf")

Install the HTTP client with python -m pip install requests. The 90-second timeout is an example client-side limit, not a claim about PDFShift’s service limit. Adjust it to fit your application’s request policy.

3. Choose how your automation receives the PDF

The direct response above is convenient when your program can write PDF bytes itself. PDFShift also documents a filename-based flow for automation platforms: include a filename, receive JSON with a temporary download URL, then use a following HTTP download step to fetch the file into storage or pass it to another workflow action. [c_pdfshift_make]

Pattern Use it when Next step
Binary PDF response Your script or service can receive and save bytes directly. Write the response body to a file or object store.
Filename and temporary URL Your automation needs a URL for a separate download or routing module. Read the returned JSON and download the temporary URL promptly as part of the workflow.

Do not treat a PDF download URL as a permanent archive location. The cited Make guide describes it as temporary; copy the PDF into storage you control if you need to retain it. [c_pdfshift_make]

4. Handle private invoice pages

A PDF converter must be able to load the invoice page. A URL that works in your logged-in browser may not work from PDFShift because your browser’s session is separate. PDFShift’s Make guide lists authentication, cookies, and custom HTTP headers as options for private pages. [c_pdfshift_make]

  • Use the least-privileged session or credentials needed to reach the invoice.
  • Pass only the required authentication data, cookies, or headers through the supported PDFShift request options.
  • Do not place credentials in a URL, logs, a publicly shared automation, or client-side code.
  • Check the generated PDF for missing invoice details. The documented options do not guarantee compatibility with every portal, login flow, or session expiry behavior.

If a portal relies on an interactive login, one-time code, or browser-only state, a server-side URL conversion may not see the same page as your browser. Confirm what the portal permits and use an authorized access method. The available PDFShift material establishes that authentication, cookies, and headers are supported, but not that every private invoice workflow will work. [c_pdfshift_make]

5. Check the downloaded PDF

  1. Confirm the request succeeded and the output file is non-empty.
  2. Open the PDF and verify that it contains the intended invoice, including its tables, totals, and any page breaks.
  3. If content is missing, first confirm that the source URL opens to the invoice when fetched without your local browser session. Then check the authentication, cookies, or headers supplied to the conversion.
  4. Keep the original invoice source and the generated file associated in your workflow so you can identify which page produced a stored PDF.

A PDF is a rendered copy of page content. Conversion alone does not determine whether an invoice is genuine, accurate, legally valid, GST-compliant, or suitable for a particular record-retention requirement. The cited PDFShift documentation covers conversion mechanics, not Indian GST law. [c_pdfshift_help]

6. Troubleshoot common problems

Symptom Likely cause What to do
Authentication error or watermarked output The API key is absent, invalid, or sent using an outdated authentication method. Send the key in X-API-Key and verify the environment variable. PDFShift documents the header change effective 2025-05-06. [c_pdfshift_auth]
The response is an error document, not a PDF The request failed, but the client saved the response body to a .pdf file. Check the HTTP status and response body before saving. Keep the PDF signature check in your code.
Invoice content is missing The source requires login or depends on a browser session not sent with the request. Provide the required supported authentication, cookies, or headers, then inspect the resulting PDF. [c_pdfshift_make]
Conversion cannot load the source The URL is inaccessible to the conversion service, is incorrect, or the page load failed. Check the URL and access from outside your logged-in browser. For private content, configure only the required access information. [c_pdfshift_make]
Automation step receives JSON instead of a PDF The request used the filename/temporary-URL response pattern. Parse the JSON and add a subsequent HTTP download step for the returned URL. [c_pdfshift_make]
Local request times out The client timeout elapsed before the response arrived. Choose a client timeout suitable for your workflow and handle timeouts as failures; do not save a partial or absent response as a valid PDF.

7. Reliability, performance, and cost considerations

  • Reliability: Check both the HTTP status and the PDF signature. Treat network failures, inaccessible pages, and unexpected response bodies as errors. Avoid automatic retries for permanent problems such as a bad key or inaccessible URL; if your workflow retries transient failures, cap attempts and avoid duplicate downstream actions.
  • Performance: Each conversion requires PDFShift to load and render the source page before returning the PDF. Keep your own client timeout and workflow expectations realistic for page-loading work. The cited materials do not provide a conversion-time benchmark.
  • Cost: Confirm current PDFShift pricing and account limits in its own documentation before scaling. The research sources used for this workflow do not establish a price, quota, or per-conversion cost.
  • Data handling: Invoice pages and any credentials or cookies used to access them can be sensitive. Send only the information needed for authorized conversion, keep keys out of logs, and store generated PDFs according to your organization’s policies.

Or skip the browser setup

If your goal is a clean image capture of an invoice page, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request with a URL returns an image or PDF. For a screenshot output, the one-call request looks like this:

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

See the ScreenshotNeo API documentation for the request options. It accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers say the page verdict and whether it was billed. Its MCP server lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

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

FAQ

Does PDFShift verify that an invoice is a valid Indian GST invoice?

No. It converts a page to a PDF; the cited conversion documentation does not establish invoice authenticity or GST compliance.

Can I convert an invoice that is only visible after login?

PDFShift documents authentication, cookies, and custom headers for private pages. Whether they work depends on the particular portal and its login behavior. [c_pdfshift_make]

Should I save the PDF response or use a download URL?

Save the binary response when your code can write the file directly. Use the filename-based JSON and temporary URL flow when a separate automation download step fits your workflow. [c_pdfshift_url][c_pdfshift_make]

Does the PDF preserve the exact interactive webpage?

No. It is a PDF rendering of the page content, not an interactive copy of the website.