Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsFor uploads, Puppeteer can put local files into a page’s <input type="file"> or accept files for a browser file chooser that your script intercepts. Downloads are different: Puppeteer can configure Chrome’s download policy and destination, but its Files guide says it does not provide a programmatic way to manage downloaded files. Your Node.js script must handle waiting for and checking the file separately.
Upload a file through an input element
If the page exposes a standard file input, use ElementHandle.uploadFile(). It accepts one or more file paths. This example assumes the script runs with Puppeteer in Node.js and that the target page has an upload input.
As an Amazon Associate I earn from qualifying purchases.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com/upload', { waitUntil: 'domcontentloaded' });
const input = await page.waitForSelector('input[type="file"]');
await input.uploadFile('/absolute/path/to/document.pdf');
// If the page requires a separate submit action, trigger it explicitly.
// await page.click('button[type="submit"]');
} finally {
await browser.close();
}
})();
Replace the example URL and path with the page and file you control. For multiple files, pass multiple paths: await input.uploadFile('/path/one.pdf', '/path/two.png'). The browser sets the selected files on the input; the site may still require a submit button or other form action.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use a path visible to the browser process
When Puppeteer launches a local browser, a relative path resolves from the Node.js process’s current working directory. When connecting to remote Chrome, the browser runs elsewhere: use an absolute path that exists in the remote browser environment, not merely on the machine running your script.
#1 Best Overall
Upload through a file chooser
Some pages open the operating system’s file chooser only after a button or other control is clicked. Register waitForFileChooser() before clicking, then accept the file paths with the returned chooser.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com/upload', { waitUntil: 'domcontentloaded' });
const chooserPromise = page.waitForFileChooser();
await page.click('button#choose-file');
const chooser = await chooserPromise;
await chooser.accept(['/absolute/path/to/document.pdf']);
// Continue with the page's upload or submission flow if needed.
} finally {
await browser.close();
}
})();
The order matters: if the click happens before Puppeteer starts waiting, the chooser can open before it is intercepted. The chooser API does not check whether the supplied paths exist, so confirm the file is present and readable yourself. Only one browser file chooser can be open at a time; accept or cancel each chooser before waiting for another.
Picker APIs this does not intercept
waitForFileChooser() is for browser file choosers triggered by page controls. It cannot intercept DOM calls such as window.showOpenFilePicker(). Do not treat it as a universal hook for every modern file-picker interface; if a site uses a different API, its flow may need another approach.
Configure Chrome downloads without confusing policy for file handling
Puppeteer’s current Files guide says: “Currently, Puppeteer does not offer a way to handle file downloads in a programmatic way.” The download behavior API configures what Chrome is allowed to do and, when allowed, where it saves files. It does not by itself give the Node.js script the downloaded contents or validate that a download completed correctly.
Rank #3
| Behavior | Meaning |
|---|---|
deny |
Disallow downloads. |
allow |
Allow downloads; a downloadPath is required. |
allowAndName |
Allow downloads and name saved files according to their download GUIDs; a downloadPath is required. |
default |
Use the browser’s default download behavior. |
The documented ConnectOptions.downloadBehavior configuration is for Chrome in Node.js. The API reference marks its use with puppeteer.connect() as experimental. Check the reference for the Puppeteer version installed in your project before relying on this version-sensitive setting.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true,
downloadBehavior: {
policy: 'allow',
downloadPath: '/absolute/path/to/downloads'
}
});
try {
const page = await browser.newPage();
await page.goto('https://example.com/export', { waitUntil: 'domcontentloaded' });
await page.click('a#download');
// The browser has been configured to save downloads to the chosen directory.
// Your script still needs its own completion detection and file validation.
} finally {
await browser.close();
}
})();
This example shows browser-side configuration, not a complete download manager. The cited documentation does not establish a specific cross-version method for detecting completion, validating contents, or cleaning up downloaded files. Implement those steps separately and verify them against your exact Puppeteer and Chrome versions rather than assuming that a click means the file is ready.
Choose the right Puppeteer installation for the browser
The official installation guidance distinguishes the two common packages:
puppeteerdownloads a compatible Chrome build by default.puppeteer-coredoes not download Chrome and is intended for remote or user-managed browsers.
That distinction matters for both upload paths and download destinations: the file path must be accessible to the machine running the browser. The download behavior option described above is specifically documented for Chrome and Node.js, not as a browser-agnostic download API.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot common upload and download failures
- “No element” or selector timeout: The page may not have rendered the input yet, or the selector may be wrong. Wait for the relevant page state and inspect the actual input selector before calling
uploadFile(). - File not found: Check the Node.js working directory for relative paths. If Chrome is remote, move or mount the file where the remote browser can access it and pass an absolute path.
- The chooser was not captured: Start
waitForFileChooser()before clicking the control. Ensure a previous chooser was accepted or canceled. showOpenFilePicker()is involved: Puppeteer’s documented file-chooser interception does not cover this DOM API; the chooser example is not applicable to that picker flow.- Download is missing or incomplete: An allowed policy and destination only configure Chrome’s behavior. Add separate logic to detect completion and inspect the saved file, and confirm compatibility with the installed Puppeteer and Chrome versions.
Or skip the browser setup
If your goal is a screenshot or PDF rather than an interactive upload/download test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF; for example, this cURL call saves a WebP screenshot:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the request options. ScreenshotNeo accepts cookie and consent banners before capture and removes known consent platforms, newsletter popups, and chat widgets; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server lets AI agents take screenshots, and the Free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo and get 1,000 free screenshots a month with no card.
Frequently Asked Questions
Can Puppeteer upload more than one file at once?
Yes. Pass multiple file paths to `uploadFile()` or to the file chooser’s `accept()` method.
Recommended Free Tools
Does Puppeteer download a file and return its contents?
No. Puppeteer can configure Chrome’s download policy, but the script must separately locate, wait for, and validate the saved file.
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.




