The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →For uploads, Puppeteer can put a local file into a page’s <input type="file">, or accept a file chooser after you register to wait for it and trigger it. For downloads, Puppeteer can configure Chrome’s download policy and destination, but its current Files guide says it does not manage downloaded files programmatically. Your Node.js script must handle waiting for a saved file and checking it separately.
Upload a file through a file input
When the page exposes a standard file input, locate it and call uploadFile(). It accepts one or more paths. The example below assumes Node.js and a local file named report.pdf in the project directory:
const puppeteer = require('puppeteer');
const path = require('node:path');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com/upload');
const fileInput = await page.waitForSelector('input[type="file"]');
await fileInput.uploadFile(path.resolve('report.pdf'));
// Continue with the page's submit or confirmation action.
await page.locator('button[type="submit"]').click();
} finally {
await browser.close();
}
})();
Replace the example URL, selector, file path and submit action with the page’s actual values. For multiple files, pass multiple paths: await fileInput.uploadFile(path.resolve('one.pdf'), path.resolve('two.pdf'));. The page input must allow multiple files for the site to accept them as a group.
Use a path the browser environment can access
With a locally launched browser, a relative path is resolved from the Node.js process’s current working directory; using path.resolve() makes that location explicit. If your script connects to remote Chrome, the path must be absolute and accessible to the browser environment, not merely to the machine running the script.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
Upload through a file chooser
Some pages reveal or click a control that opens the browser’s file chooser instead of exposing an input you can conveniently target. Register waitForFileChooser() before clicking that control; otherwise the chooser can open before Puppeteer starts waiting.
const puppeteer = require('puppeteer');
const path = require('node:path');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com/upload');
const chooserPromise = page.waitForFileChooser();
await page.locator('button.open-file-picker').click();
const chooser = await chooserPromise;
await chooser.accept([path.resolve('report.pdf')]);
// Continue with the page's submit or confirmation action.
} finally {
await browser.close();
}
})();
accept() does not check whether the supplied paths exist. Check the path yourself if needed, and use an absolute path for a remote browser. Only one browser file chooser can be open at a time; accept or cancel it before waiting for another. In headful mode, when Puppeteer is waiting for the chooser, the native picker does not appear for a person to operate.
Picker API limitation
waitForFileChooser() intercepts the browser file chooser associated with the page action; it does not intercept DOM calls such as window.showOpenFilePicker(). Do not assume this approach covers every modern file-picker interface.
Configure Chrome downloads without mistaking it for file handling
Puppeteer’s current Files guide states: “Currently, Puppeteer does not offer a way to handle file downloads in a programmatic way.” The download behavior API sets browser policy and, where required, a destination. It does not by itself tell your script that a file is complete, inspect its contents, validate it, or return its contents.
Rank #3
| Policy | Effect |
|---|---|
deny |
Block browser downloads. |
allow |
Allow downloads; requires downloadPath. |
allowAndName |
Allow downloads and name files using download GUIDs; requires downloadPath. |
default |
Use the browser’s default download behavior. |
For a Chrome browser in Node.js, the documented connection option can configure behavior for the context:
const browser = await puppeteer.connect({
browserWSEndpoint: process.env.CHROME_WS_ENDPOINT,
downloadBehavior: {
policy: 'allow',
downloadPath: '/absolute/path/to/downloads'
}
});
Set downloadPath to the actual destination directory. The API marks downloadBehavior with puppeteer.connect() as experimental and specifically documents this option for Chrome in Node.js. Verify the installed Puppeteer and Chrome versions before relying on it in production.
What your surrounding script still needs
After triggering the download, your application needs its own strategy to determine when the file is ready, enforce a timeout, inspect or consume the resulting file, and clean up temporary files. Those responsibilities are separate from setting the browser’s download policy. Do not treat the policy option as a download-completion signal or as a file-content API.
Choose the right Puppeteer environment
puppeteer: Installation downloads a compatible Chrome build by default, which is convenient for a local workflow.puppeteer-core: Does not download Chrome and is intended for remote or user-managed browsers. Ensure the browser and file paths are available in the environment where Chrome runs.- Download configuration: The documented
downloadBehavioroption is Chrome/Node.js-specific; its use throughpuppeteer.connect()is experimental.
The official documentation pages surfaced different current version labels: the Files guide showed Puppeteer 25.12.0, while FileChooser references showed 25.9.0 and 25.10.0. API details can vary by installed version, so use the reference matching your package when signatures or behavior matter.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Troubleshoot upload and download problems
- “No file” or an incorrect file is uploaded: Resolve the path from the script’s working directory and confirm that it exists. For remote Chrome, use a path accessible to that remote environment.
- The chooser wait hangs: Start
waitForFileChooser()before the click that opens the chooser, and confirm the clicked control actually opens a browser chooser. - A later chooser does not appear: Only one chooser can be active. Accept or cancel the current one before waiting for the next.
- The page uses
showOpenFilePicker(): The documented chooser interception does not support this DOM API. This approach is not a universal solution for every picker. - A download is missing or goes to an unexpected place: Confirm that the selected policy allows downloads and that
downloadPathis set foralloworallowAndName. Check Chrome/Node.js compatibility and the connected browser context. - The script reads a partial download: Download policy configuration is not a completion signal. Add a separate wait, timeout and validation strategy before consuming the file.
Or skip the browser setup
If your goal is a page capture rather than automating an upload or download flow, ScreenshotNeo is a website screenshot API and MCP server. Its API returns an image or PDF from one GET request; its documented options include cookies, custom headers and JavaScript. It is not a replacement for Puppeteer file upload or download automation.
Example cURL request (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
ScreenshotNeo removes cookie banners, newsletter popups and chat widgets before capture; bot checks, blank pages and failed loads are not billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Learn more at ScreenshotNeo, or sign up for 1,000 free screenshots a month with no card.
Frequently Asked Questions
Does Puppeteer support selecting a file in a native picker by hand?
In headful mode, the native picker does not show while Puppeteer is waiting for the chooser; provide the file path through Puppeteer instead.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Can I use Puppeteer’s download behavior option with Firefox?
The documented option is specifically for Chrome in Node.js.
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.

