Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Direct answer: authenticate a browser context, wait for the final redirect and invoice-ready content, then render the page as a PDF. In Playwright, save the signed-in cookies and local storage with storageState, load that state into a fresh context, navigate to the invoice URL, wait for the page’s data and assets, and call the browser’s PDF method. If the endpoint already returns a PDF, skip browser rendering and make an authenticated HTTP request instead.

Choose the shortest reliable path

Invoice endpoint behavior Best method Why
The server returns application/pdf directly Authenticated HTTP request It has the lowest overhead and preserves the server’s intended PDF bytes.
An HTML invoice is assembled by JavaScript Playwright or Puppeteer A real browser executes scripts, applies styles, and retains the login session.
Login uses cookies or local storage Playwright storageState (or an equivalent context export) The complete signed-in browser state can be reused without automating login for every invoice.
Login uses HTTP Basic authentication Browser or API credentials scoped to the origin The credentials are sent to the protected host before the document is requested.
Many invoices are processed by a worker One browser process with isolated contexts Contexts reduce startup cost while keeping accounts and cookies separate; validate concurrency against the target application.

Do not assume that a URL containing an invoice ID is downloadable. A protected application may return a login page with status 200, an authorization error, or an HTML shell that still needs JavaScript data. Check the final URL, response content type, and an invoice-specific element before saving bytes.

End-to-end workflow

  1. Authenticate. Use the application’s supported UI or API login. Prefer a least-privilege account dedicated to document retrieval.
  2. Export state. Save cookies, local storage, and related browser state to an encrypted, short-lived file or an in-memory object. Treat it as a credential.
  3. Start a fresh context. Load the saved state so the invoice request is isolated from unrelated tabs and users.
  4. Navigate and follow redirects. Wait for the final post-login URL, not merely the first response.
  5. Assert readiness. Wait for a selector that proves the invoice is present; then wait for fonts, images, and client-side data that are not covered by that selector.
  6. Set print behavior. PDF generation normally uses print CSS. Emulate screen media when the invoice is styled only for the screen.
  7. Render and validate. Set paper, margins, backgrounds, headers, footers, and page ranges. Confirm the result is a PDF for the expected invoice before storage.
  8. Clean up. Delete temporary state and remove authorization headers, cookies, and invoice contents from logs.

Playwright with Node.js

The following script logs in once, writes an authenticated state file, then creates a new context and renders an invoice. Replace selectors and URLs with those used by your application.

import { chromium } from 'playwright';

const loginUrl = 'https://billing.example.com/login';
const invoiceUrl = 'https://billing.example.com/invoices/INV-1042';
const statePath = './.secrets/billing-state.json';

const browser = await chromium.launch();
try {
  const loginContext = await browser.newContext();
  const loginPage = await loginContext.newPage();
  await loginPage.goto(loginUrl, { waitUntil: 'domcontentloaded' });
  await loginPage.getByLabel('Email').fill(process.env.BILLING_EMAIL);
  await loginPage.getByLabel('Password').fill(process.env.BILLING_PASSWORD);
  await loginPage.getByRole('button', { name: /sign in|log in/i }).click();
  await loginPage.waitForURL(/dashboard|invoices/, { waitUntil: 'domcontentloaded' });
  await loginContext.storageState({ path: statePath });
  await loginContext.close();

  const context = await browser.newContext({ storageState: statePath });
  const page = await context.newPage();
  await page.goto(invoiceUrl, { waitUntil: 'domcontentloaded' });
  if (/login|signin|sign-in/i.test(page.url())) {
    throw new Error(`Authentication redirect: ${page.url()}`);
  }
  await page.locator('[data-invoice-ready="true"]').waitFor({ state: 'visible', timeout: 30000 });
  await page.evaluate(() => document.fonts.ready);
  await page.waitForLoadState('networkidle');
  await page.emulateMedia({ media: 'print' });
  await page.pdf({
    path: './out/INV-1042.pdf',
    format: 'A4',
    printBackground: true,
    margin: { top: '16mm', right: '14mm', bottom: '16mm', left: '14mm' },
    displayHeaderFooter: false
  });
  await context.close();
} finally {
  await browser.close();
}

The storageState file can contain cookies and headers capable of impersonating the account. Keep it outside source control, restrict its permissions, encrypt it at rest, and remove it after its useful lifetime. For a queue, create a separate context per account or tenant; never let one worker context carry another customer’s cookies.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
XKDOUS 2 Pack Invoice Books, 2-Part Carbonless Receipt Books
  • Two-Part Carbonless Invoice Book: Each invoice book has 50 sets of invoices, each with a white/light yellow section, with the yellow section retained in the invoice book to maintain detailed records.
  • Consecutively Numbered: Enlarged red 6-digit numbers in the upper right corner of each invoice receipt book help you quickly navigate through your orders.
  • Wraparound Divider Flap: A thick folded cardboard divider is integrated into the back of each invoice book for use between each two-part sales order to prevent the written content from rubbing off on subsequent copies of the invoice, resulting in wasted invoices.
  • 2 Packs/50 Sets (100 Sets Total): Each invoice book provides 50 sequentially numbered carbonless sets of 2 invoice books for long-term use.
  • Customizable Space: Each invoice book for small business has space at the top to add a company seal or sticker.

When the invoice is not ready at network idle

networkidle is not an invoice guarantee. Single-page apps can finish their network activity before inserting totals, tax rows, or a barcode. Use a semantic readiness marker such as [data-invoice-ready="true"], a visible invoice number, or a totals element. If the application exposes a completion API, wait for that response or poll it with a bounded timeout. Avoid arbitrary long sleeps unless the site gives you no better signal.

Python Playwright equivalent

import asyncio
import os
from pathlib import Path
from playwright.async_api import async_playwright

async def main():
    state = Path('.secrets/billing-state.json')
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        login_context = await browser.new_context()
        login_page = await login_context.new_page()
        await login_page.goto('https://billing.example.com/login', wait_until='domcontentloaded')
        await login_page.get_by_label('Email').fill(os.environ['BILLING_EMAIL'])
        await login_page.get_by_label('Password').fill(os.environ['BILLING_PASSWORD'])
        await login_page.get_by_role('button', name='Sign in').click()
        await login_page.wait_for_url('**/dashboard**')
        await login_context.storage_state(path=str(state))
        await login_context.close()

        context = await browser.new_context(storage_state=str(state))
        page = await context.new_page()
        await page.goto('https://billing.example.com/invoices/INV-1042', wait_until='domcontentloaded')
        if 'login' in page.url.lower():
            raise RuntimeError(f'Authentication redirect: {page.url}')
        await page.locator('[data-invoice-ready="true"]').wait_for(state='visible', timeout=30000)
        await page.evaluate('document.fonts.ready')
        await page.wait_for_load_state('networkidle')
        await page.emulate_media(media='print')
        await page.pdf(
            path='out/INV-1042.pdf', format='A4', print_background=True,
            margin={'top': '16mm', 'right': '14mm', 'bottom': '16mm', 'left': '14mm'}
        )
        await context.close()
        await browser.close()

asyncio.run(main())

Puppeteer options and print layout

Puppeteer’s official guidance is concise: “For printing PDFs use Page.pdf().” The sequence is the same: create or load an authenticated browser context, navigate, assert invoice readiness, then call page.pdf(). A typical call is:

await page.emulateMediaType('print');
await page.pdf({
  path: 'INV-1042.pdf',
  format: 'A4',
  printBackground: true,
  margin: { top: '16mm', right: '14mm', bottom: '16mm', left: '14mm' },
  displayHeaderFooter: false
});

PDF output uses print CSS by default. If your invoice only has screen rules, call emulateMediaType('screen') before rendering. Use printBackground: true when colored bands or logos are part of the document. Headers and footers can be enabled with templates, but template HTML has a restricted environment and does not automatically inherit the page’s styles.

Rank #2
PrintWorks Professional Half Sheet Perforated Paper 8.5” x 11” - Perfect For W-2, 1099, & Statement Use - Made in the USA - 2500 Sheets - 20 lb - A5 Paper - Printer Compatible - White (04116C)
  • Easily print W-2s, 1099s, statements, invoices, certificates, and coupons with this half-sheet perforated paper. These perforated sheets help you save time by providing clean and easy tears
  • Case includes 2500 bright white 8.5" x 11" sheets of 20 lb copy paper, featuring a clean horizontal perforation 5 1/2" from the bottom for quick tearing and folding (A5 paper)
  • Our perforated printer paper makes payroll, shipping, and everyday business tasks easier and more efficient, reducing the stress and hassle of manual document processing
  • This 2-part paper is compatible with laser and inkjet printers; copiers; and most business, accounting, and shipping software that uses standard templates, ensuring simple integration
  • PrintWorks Professional perforated paper has been proudly made in the USA since 1964 using domestically sourced, environmentally friendly materials for reliable quality and sustainability

Authentication patterns

Cookie and local-storage sessions

Complete the normal login flow once, export state, and load it into a new context. A state export is more reliable than copying one cookie because modern applications may require several cookies, local-storage tokens, and host-specific attributes. Refresh or recreate state when the application expires it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

HTTP Basic authentication

For a Basic-protected origin, configure credentials before navigation. In Playwright:

const context = await browser.newContext({
  httpCredentials: {
    username: process.env.BASIC_USER,
    password: process.env.BASIC_PASSWORD
  }
});
const page = await context.newPage();
await page.goto('https://billing.example.com/invoices/INV-1042');

Scope credentials to the intended host and never place them in a URL or diagnostic log.

Rank #3
Adams Sales Order Book, 2-Part, Carbonless, White/Canary, 4-3/16 x 7-3/16 Inches, 50 Sets per Book (DC4705)
  • QUALITY INVOICES: Adams Order books provide a professional invoice or customer receipt; a great way to create and maintain a professional image for small businesses and service providers
  • 50 TWO-PART CARBONLESS FORMS: Customers get the perforated white top copy; retain the canary and pink copies for your records
  • WRAP-AROUND COVER: Fold the back cover between sets to keep invoices neat and legible
  • ROOM FOR CUSTOMIZATION: A blank space at top leaves room for your company stamp; a big savings over custom-printed forms
  • CONSECUTIVELY NUMBERED: Large 6-digit numbers in the upper right hand corner help you thumb through orders quickly

Bearer tokens and direct PDF endpoints

If the invoice endpoint itself returns a PDF, a browser is unnecessary. Request it with the token, check the status and content type, and write the response bytes:

curl --fail-with-body -L 
  -H "Authorization: Bearer $INVOICE_TOKEN" 
  -H "Accept: application/pdf" 
  "https://billing.example.com/api/invoices/INV-1042.pdf" 
  -o INV-1042.pdf

For an HTML application, do not blindly attach a bearer token to every browser request. Use the application’s supported login or request mechanism, because the token may belong in a cookie, local storage, or a specific API call.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Redirect-based login

Wait for the final URL or a signed-in condition. Authentication systems can set cookies across several redirects; rendering after the first navigation may capture the login form or an intermediate consent page.

Rank #4
PrintWorks Professional 3 1/2" Horizontal Perforated Paper 8.5” x 11” - Perfect for W-2, 1099, & Statement Use - Made in The USA - 500 Sheets - 20 lb - Printer Compatible - White (04128)
  • Easily print W-2s, 1099s, statements, invoices, certificates, and coupons with this 3 1/2" perforated paper. These perforated sheets help you save time by providing clean and easy tears
  • Ream includes 500 bright white 8.5" x 11" sheets of 20 lb copy paper, featuring a clean horizontal perforation 3 1/2" from the bottom for quick tearing and folding
  • Our 3 1/2 inch perforated printer paper makes payroll, shipping, and everyday business tasks easier and more efficient, reducing the stress and hassle of manual document processing
  • This 2-part paper is compatible with laser and inkjet printers; copiers; and most business, accounting, and shipping software that uses standard templates, ensuring simple integration
  • PrintWorks Professional perforated paper has been proudly made in the USA since 1964 using domestically sourced, environmentally friendly materials for reliable quality and sustainability

Validation, reliability, and worker design

  • Validate identity: compare the displayed invoice number, customer, currency, and total with the job request before persisting the file.
  • Validate bytes: check that the response begins with the PDF signature and that the saved file is not an HTML login page.
  • Bound every wait: use navigation, selector, and overall job timeouts. Retry transient navigation failures with backoff, but do not retry invalid credentials indefinitely.
  • Reuse browsers, isolate contexts: a long-lived browser process saves startup work; a fresh context per account prevents cookie crossover.
  • Control navigation: allow-list invoice hosts and reject unexpected redirects to reduce server-side request forgery risk.
  • Protect output: invoices contain financial information. Apply access controls, encryption, retention limits, and deletion on job failure.
  • Observe safely: log job IDs, durations, final host, and high-level status—not cookies, authorization headers, page HTML, or invoice contents.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting authenticated PDF jobs

Symptom Likely cause Fix
PDF contains the login page State was not loaded, expired, or was saved before login completed Save state after the post-login URL, load it into a fresh context, and fail if the final URL matches a login route.
Status is 200 but no invoice appears The response is an HTML shell awaiting JavaScript Use Playwright or Puppeteer and wait for an invoice-specific readiness selector.
Totals or line items are missing Client-side data arrived after the chosen wait condition Wait for the totals element or a documented API response, then wait for fonts and images.
Layout is unstyled or backgrounds are white Print media rules differ from screen rules, or backgrounds are disabled Choose the correct media type and enable background printing.
Images or fonts are absent Cross-origin resources, lazy loading, or premature rendering Wait for document.fonts.ready, ensure resources are reachable in the authenticated context, and scroll or use the application’s loaded state for lazy assets.
Intermittent timeouts Slow upstream APIs, bot checks, or overloaded workers Use bounded retries with backoff, capture diagnostic status, and reduce concurrency to what the billing system supports.
Another customer’s invoice is captured Shared context or an unchecked redirect Use isolated contexts, allow-list hosts, and verify invoice identity before writing the PDF.
Direct request returns JSON or HTML instead of PDF Wrong endpoint, missing token scope, or an authorization redirect Inspect status and Content-Type, follow redirects deliberately, and confirm the API’s PDF route and permission.

Or skip the browser setup

ScreenshotNeo can render a URL to a PNG, JPEG, WebP, or PDF with one GET request. For a protected invoice, provide the authentication parameters supported by your application, then request PDF output. The API can also apply cookies, custom headers, an Authorization header, user-agent, timezone, and geolocation; wait for a selector, delay, or network idle before capture; and set paper size, margins, landscape mode, and page ranges. See the ScreenshotNeo documentation for the current parameter names.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://billing.example.com/invoices/INV-1042 -d format=pdf -o invoice.pdf

ScreenshotNeo removes cookie-consent banners, newsletter popups, and chat widgets before capture. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; each response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is on every plan. Create a free ScreenshotNeo account.

FAQ

Should I save the browser state permanently?

No. State files are credential material. Encrypt them, restrict access, set a short lifetime, keep them out of source control, and delete them when the worker no longer needs them.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can a PDF endpoint still require a browser?

Yes, if access depends on browser cookies, a redirect login, or a token established by application JavaScript. A direct HTTP request is appropriate only when you can authenticate the endpoint and it returns the PDF bytes.

Best Value
Invoice Receipt Book with Cardboard 2-Part Carbonless, 5.5" x 8.5" Order Forms, 50 Sheets Carbonless Sales Invoice Book for Small Business
  • PACKAGE INCLUDES - Our invoice book per pack has 50 sets sheets, Total of 100 sheets. red code printed on each page with consecutive numbers
  • Material - Receipt book is excellent quality carbonless paper is used in their production, tears off easily along the perforation.
  • A5 Size - Sales invoice book size of 5.5" x 8.5", and forms are 2 part carbonless white/yellow sets on a sturdy chipboard backing
  • WIDE APPLICATION - Sales reciepts/invoice book for small business is ideal for restaurants, food trucks, vendors, service provider, photographers, caterers, florists, bakeries, cafes, boutiques and salons

Why does the PDF differ from what I see on screen?

PDF generation uses print CSS by default. Emulate screen media when necessary, enable background graphics, and verify page size and margins against the invoice’s CSS.

Is waiting for network idle sufficient?

No. It does not prove that client-side invoice data has been inserted. Wait for a semantic invoice-ready element or a completed data request as well.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.