Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
To read the bytes of a PDF that a logged-in browser session requests, wait for the specific network response before triggering the download, verify that response, and call HTTPResponse.buffer(). Keep the listener and the download action on the same Puppeteer page and browser context that holds the session.
This is different from page.pdf(): page.pdf() prints the current DOM into a new PDF. It does not retrieve the PDF response generated by a server.
The reliable response-buffering pattern
Register a narrowly filtered page.waitForResponse() promise first. Then click the control, submit the form, or run the JavaScript that causes the PDF request. Waiting first prevents a fast response from arriving before your listener exists.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11const responsePromise = page.waitForResponse(response => {
const headers = response.headers();
return response.url().includes('/generated-report') &&
(headers['content-type'] || '').includes('application/pdf');
});
const [response] = await Promise.all([
responsePromise,
page.click('button.download-report'),
]);
if (!response.ok()) {
throw new Error(`PDF request failed: HTTP ${response.status()}`);
}
const pdfBuffer = await response.buffer();
Replace /generated-report and button.download-report with the endpoint and trigger used by your application. The URL test should be as specific as practical; matching every response containing “pdf” can capture an unrelated asset or an error document.
#1 Best Overall
- PORTABLE SCANNER FOR USE ON-THE-GO — The fastest and lightest mobile single-sheet-fed compact document scanner in its class¹
- QUICK DOCUMENT SCANNING ― This Epson ultra-fast scanner scans a single page as quickly as 5.5 seconds²; Windows and Mac compatible
- VERSATILE PAPER HANDLING ― Portable scanner scans documents up to 8.5 x 72 in; Also easily digitizes receipts and ID cards to make accounting, bookkeeping, and organizing simpler
- INTUITIVE, HIGH-SPEED SOFTWARE — Epson ScanSmart Software³ is a smart tool allowing you to easily scan, review, and save; Stay organized easily with the help of this Epson scanner
- EASY SETUP — USB-powered connect to your computer for quick and simple scanning; No batteries or external power supply required to operate portable document scanner; Standard Connectivity: USB 2.0
A complete authenticated example
The following script shows the sequence. The login selectors and report endpoint are necessarily application-specific, so replace the marked values. Credentials come from environment variables rather than source code.
import puppeteer from 'puppeteer';
import { writeFile } from 'node:fs/promises';
const browser = await puppeteer.launch({ headless: true });
try {
const context = browser.defaultBrowserContext();
const page = await context.newPage();
await page.goto(process.env.APP_URL, { waitUntil: 'networkidle2' });
await page.type('#email', process.env.APP_USER);
await page.type('#password', process.env.APP_PASSWORD);
await page.click('button[type="submit"]');
await page.waitForNavigation({ waitUntil: 'networkidle2' });
// Inspecting the context is useful for diagnostics; never log cookie values.
const sessionCookies = await context.cookies();
if (sessionCookies.length === 0) {
throw new Error('No session cookies found after login');
}
const responsePromise = page.waitForResponse(async response => {
const contentType = response.headers()['content-type'] || '';
return response.url().includes('/generated-report') &&
contentType.toLowerCase().includes('application/pdf');
}, { timeout: 30000 });
const [response] = await Promise.all([
responsePromise,
page.click('button.download-report'),
]);
if (!response.ok()) {
throw new Error(`PDF request failed: HTTP ${response.status()} ${response.url()}`);
}
const pdfBuffer = await response.buffer();
const contentType = (response.headers()['content-type'] || '').toLowerCase();
const signature = pdfBuffer.subarray(0, 5).toString('ascii');
if (!contentType.includes('application/pdf') && signature !== '%PDF-') {
throw new Error('The response was not a PDF document');
}
await writeFile('report.pdf', pdfBuffer);
} finally {
await browser.close();
}
HTTPResponse.buffer() resolves to a Node.js Buffer containing the response body. The browser may re-encode the buffer according to response headers or heuristics, so checking the content type and the expected %PDF- signature before handing it to a PDF parser can expose an HTML login page or another unexpected payload.
Keep the request in the authenticated context
A session-generated URL is not necessarily a self-contained credential. The application may require a still-valid cookie, a token, a referrer, a custom header, or a particular request sequence. If authentication was established in Puppeteer, continue from that same page and browser context when requesting the PDF.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
BrowserContext.cookies() returns cookies associated with the context. Browser- or context-level cookie methods are the supported model; older page-level cookie methods are deprecated. Treat cookie values and authorization headers as secrets: do not print them in diagnostics, commit them, or include them in bug reports.
Rank #2
- FAST SPEEDS - Scans color and black and white documents a blazing speed up to 16ppm (1). Color scanning won’t slow you down as the color scan speed is the same as the black and white scan speed.
- ULTRA COMPACT – At less than 1 foot in length and only about 1. 5lbs in weight you can fit this device virtually anywhere (a bag, a purse, even a pocket).
- READY WHENEVER YOU ARE – The DS-640 mobile scanner is powered via an included micro USB 3. 0 cable allowing you to use it even where there is no outlet available. Plug it into you PC or laptop and you are ready to scan.
- WORKS YOUR WAY – Use the Brother free iPrint&Scan desktop app for scanning to multiple “Scan-to” destinations like PC, Network, cloud services, Email and OCR. (2) Supports Windows, Mac and Linux and TWAIN/WIA for PC/ICA for Mac/SANE drivers. (3)
- OPTIMIZE IMAGES AND TEXT – Automatic color detection/adjustment, image rotation (PC only), bleed through prevention/background removal, text enhancement, color drop to enhance scans. Software suite includes document management and OCR software. (4)
Diagnose redirects and authorization failures
- Record the response URL, status, and non-sensitive headers. A 401 or 403 usually means the session or required authorization data is missing or expired.
- If the response URL is a login page, the report request probably followed an authentication redirect. Re-establish the session and confirm that the click occurs after login has completed.
- Do not assume that copying the PDF URL into a separate HTTP client will work. That client may lack the browser’s cookies, token, referrer, or preceding request sequence.
Validate more than request completion
A network request can complete even when the server returns an error. Puppeteer’s API documentation notes that HTTP errors such as 404 and 503 still complete at the HTTP request level. Check response.ok() or the numeric status before accepting the body.
For stronger validation, compare the final URL with the expected endpoint, inspect content-type, and examine the first bytes of the buffer. A valid PDF normally begins with %PDF-; an HTML error or sign-in page often begins with a tag or text instead. The signature check supplements, rather than replaces, the status and header checks.
When to use page.pdf() instead
Use await page.pdf(options) when your goal is to print the currently rendered page into a newly generated document. Its documented return type is Promise<Uint8Array>. It does not expose the bytes of an existing PDF URL that the page requested.
| Question | waitForResponse() + buffer() |
page.pdf() |
|---|---|---|
| What is captured? | An existing server response, such as a session-generated report. | A new PDF rendered from the current page. |
| Required state | The browser page/context that has the required session and request state. | The rendered DOM, styles, fonts, and print settings. |
| Documented output | Node.js Buffer from HTTPResponse.buffer(). |
Uint8Array from Page.pdf(). |
| Media behavior | Whatever bytes the server returned. | Print CSS media by default; call page.emulateMediaType('screen') first if screen styles are required. |
Puppeteer also notes that print colors are modified by default. CSS using -webkit-print-color-adjust can request exact colors when you are generating a PDF from the page.
Rank #3
- STAY ORGANIZED – Easily convert your paper documents into digital formats like searchable PDF files, JPEGs, and more.Power Consumption : 2.5W or less (Energy Saving Mode: 0.7W). Suggested Daily Volume : 500 scans..Does it contain liquid: no
- CONVENIENT AND PORTABLE –lightweight and small in size, you can take the scanner anywhere from home offices, classrooms, remote offices, and anywhere in between
- HANDLES VARIOUS MEDIA TYPES – Digitize receipts, business cards, plastic or embossed cards, reports, legal documents, and more
- FAST AND EFFICIENT – No technical hurdles or complicated setups here; easily scan both sides of a document at the same time, in color or black-and-white, at up to 12 pages-per-minute, and with a 20 sheet automatic feeder
- BROAD COMPATIBILITY – Works with both Windows and Mac devices, be it laptop or computer
Races, redirects, tabs, and downloads
Navigation and click races
Use Promise.all for the response wait and the action that triggers it. The wait must be created before the click. If the action also navigates, add a separately prepared navigation wait rather than placing a late listener after the click.
Redirects
Filter on the response that actually carries the PDF, not merely the first URL opened by the button. Confirm the final response URL and status, because an initial request may redirect to a report endpoint or to a login page.
New tabs or popups
If the control opens a new page, observe the response on that new Page and in the context that owns it. Do not continue waiting on the original page by assumption. Identify the target created by the click, obtain its Page, and install the response predicate there before triggering the action when the application allows that ordering.
Free tools Windows power users keep installed
One-click scans. No signup required.
Request interception
Do not enable interception merely to observe a response; waitForResponse is the direct observation mechanism. If interception is required for another purpose, every intercepted request must be continued, answered, aborted, or served from cache. Leaving one paused can make the report request appear to hang.
Rank #4
- IRIScan Express, portable scanner : scans color and black and white documents a blazing speed up to 8ppm simplex. Color scanning won’t slow you down as the color scan speed is the same as the black and white scan speed.
- IRIScan Express mobile scanner is powered via an included micro USB 2. 0 cable allowing you to use it even where there is no outlet available. Plug it into you PC or laptop and you are ready to scan. USB cable provided. AC Adapter not provided and not needed.
- IRIScan flatbed scanner uses a simplex scanning mode allows for quick and straightforward scanning of single-sided documents. IRIScan with its full portable features is the ideal document scanners for computers.
- IRIScan document scanner : Versatile scanning capabilities, including scanning to Word, PDF, and Excel formats with companion software provided Readiris OCR
- Receipt scanner and card scanner with Additional features include scanning business cards directly to Outlook, photo scanning, and receipt scanning for efficient document management
Timeouts, memory, and operational reliability
- Set a response timeout appropriate to the report’s generation time. A short default can fail while the server is still working; an unlimited wait can consume a worker indefinitely.
- Keep the response predicate cheap and deterministic. Matching a stable path or report identifier reduces accidental captures and unnecessary event processing.
- Buffering loads the complete document into memory. For large reports or many concurrent jobs, limit concurrency, write each completed buffer promptly, and close pages and browsers in a
finallyblock. - Preserve the authenticated context only as long as necessary. Reusing a context can reduce login work, but stale sessions should be detected and renewed rather than retried forever.
- Capture diagnostic metadata without secrets: status, final URL, content type, elapsed time, and a bounded error-body preview are generally more useful than cookies or authorization headers.
Common failures and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
waitForResponse times out |
The predicate does not match the actual endpoint, the click did not fire, or the request is slower than the timeout. | Inspect network activity, narrow or correct the URL/content-type test, verify the selector, and set a justified timeout. |
| Response status is 401 or 403 | The session expired or the request needs a token, referrer, or header not present in the context. | Log in again, confirm context ownership, and reproduce the application’s required sequence without exposing secrets. |
| Buffer contains HTML | The server returned a login page, error page, or redirect target rather than a PDF. | Check final URL, status, content type, and the %PDF- signature before parsing. |
| Buffer parses as corrupt PDF | The body was not the expected document, or browser re-encoding affected downstream validation. | Compare headers and signature, save the raw buffer for controlled inspection, and verify the target response contract. |
| The request hangs after enabling interception | An intercepted request was never resolved. | Continue, respond to, abort, or fulfill every intercepted request; remove interception if observation is all you need. |
| Capture works manually but not in automation | The automated context lacks the interactive session or required timing. | Perform authentication in that same context, wait for the app’s logged-in state, then register the response wait before the report action. |
Version and API notes
The official Puppeteer API pages reviewed on 2026-09-29 displayed version 25.10.0 for HTTPResponse.buffer() and 25.12.0 for Page, Page.pdf(), and BrowserContext.cookies(). Labels and deprecation status can change, so check the API reference that matches the version installed in your project.
Or skip the browser setup
If the target page can be fetched with headers or cookies that the application explicitly permits, ScreenshotNeo provides a single-request screenshot and PDF API. It supports custom headers, cookies, user agents, and authorization, but you must still supply credentials in the form the target site accepts. It is not a way to bypass a site’s authentication design.
For a basic call, see the ScreenshotNeo 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
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Response headers identify the page verdict and billing result.
- An MCP server exposes
take_screenshot,get_page_info, andcapture_pdffor Claude, Cursor, and other MCP clients. - The Free plan includes 1,000 shots each month without a card. Paid plans start at $5 for 3,000 shots; Growth is $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is included on every plan.
Create a free ScreenshotNeo account to try the 1,000-shot monthly allowance without entering a card.
Best Value
- Scanner type: Document
- Connectivity technology: USB
- With Auto Scan Mode, the scanner automatically detects what you're scanning
- Digitize documents and images
Frequently Asked Questions
Can I reuse one response object after calling buffer()?
Treat the returned buffer as the captured body and pass that value to downstream code. If another component needs the body, share the buffer rather than assuming the network response can be fetched again.
Why does a valid PDF response still fail in my parser?
Check the final URL, status, content type, and first bytes before blaming the parser. A browser-context redirect to HTML or a browser re-encoding issue can produce bytes that are not the document your parser expects.
Which context should observe a report opened by a popup?
Observe the Page created for that popup within the same BrowserContext that authenticated the user; the original page may never emit the PDF response.
Quick Recap
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.

