ScreenshotNeo

BlogHow-to

How to Cancel a File Chooser Dialog in Puppeteer

Register Puppeteer’s file chooser waiter before clicking the upload control, then call `cancel()` to close the chooser without selecting a file.

By the ScreenshotNeo team4 October 20265 min read

To cancel a file chooser in Puppeteer, start page.waitForFileChooser() before the action that opens it, then call await fileChooser.cancel(). The chooser must be resolved before another intercepted chooser can be handled. Puppeteer’s FileChooser reference documents cancellation as closing the chooser without selecting a file.

const [fileChooser] = await Promise.all([
  page.waitForFileChooser(),
  page.click('#upload-file-button'),
]);

await fileChooser.cancel();

1. Complete runnable example

This example opens a page, waits for the file chooser while clicking the upload button, and cancels the chooser. Install Puppeteer with npm install puppeteer; save the code as cancel-chooser.js and run node cancel-chooser.js.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await page.setContent(`
      <button id="upload-file-button">Upload</button>
      <input id="file-input" type="file" hidden>
      <script>
        document.querySelector('#upload-file-button').addEventListener('click', () => {
          document.querySelector('#file-input').click();
        });
      </script>
    `);

    const [fileChooser] = await Promise.all([
      page.waitForFileChooser({ timeout: 5000 }),
      page.click('#upload-file-button'),
    ]);

    await fileChooser.cancel();
    console.log('File chooser canceled');
  } finally {
    await browser.close();
  }
})().catch(error => {
  console.error(error);
  process.exitCode = 1;
});

The two operations belong in Promise.all: this registers the waiter before the click can open the chooser, while still awaiting both operations. A click alone followed by waitForFileChooser() is too late and may time out.

2. Cancel versus accept

Use cancel() when the automation should close the picker without choosing a file. Use accept(paths) when it should provide one or more files to the page.

// Cancel without selecting anything.
await fileChooser.cancel();

// Supply files instead (paths must exist in the environment running Puppeteer).
await fileChooser.accept(['/absolute/path/to/fixture.png']);

Every intercepted chooser should be accepted or canceled. Leaving one unresolved can prevent later chooser requests from appearing. See the FileChooser API for the current methods and lifecycle details.

3. Options and important limits

Waiter timeout

page.waitForFileChooser() accepts wait options, including a timeout in milliseconds. Set a timeout that fits the page action. A timeout only bounds how long Puppeteer waits for a chooser; it does not make an unsupported picker API interceptable. See Page.waitForFileChooser().

Register before triggering

The waiter listens for a chooser that opens after it is registered. It does not attach to a chooser that is already active. Pair it with the click or other triggering action using Promise.all.

DOM picker APIs are different

Puppeteer documents that waitForFileChooser() does not currently intercept DOM picker APIs such as window.showOpenFilePicker(). If the page calls that API, this waiter may never resolve. The file input chooser workflow and the newer DOM picker API are not interchangeable.

Headful mode

When Puppeteer handles a chooser with this method, the native picker UI does not appear to the user even in headful mode. Use the returned FileChooser object to cancel or accept it.

4. Do not use Dialog.dismiss()

A file chooser is a Puppeteer FileChooser, not a JavaScript Dialog. Dialog.dismiss() applies to JavaScript dialogs such as alerts, confirms, and prompts. For a file picker, call fileChooser.cancel(). See the separate Dialog class reference.

5. Troubleshooting

Symptom Likely cause Fix
waitForFileChooser() times out The waiter started after the click, the click did not trigger a file input, or the page uses an unsupported picker API. Register the waiter before the action in Promise.all; confirm the selector and click behavior; check whether the page uses showOpenFilePicker().
A later chooser does not appear An earlier intercepted chooser was neither accepted nor canceled. Resolve each returned chooser with accept(paths) or cancel() before opening another.
The picker is not visible in headful mode Puppeteer is handling the chooser through waitForFileChooser(); the native UI is not shown to the user. Use the returned object to accept or cancel. Do not wait for a visible operating-system dialog.
Dialog.dismiss() does not close the file picker It is the wrong API abstraction: JavaScript dialogs and file choosers are separate. Call cancel() on the returned FileChooser.
Older example reports an unexpected return type Puppeteer’s cancellation API changed historically: the changelog records FileChooser.cancel() becoming synchronous in version 9.0.0, while the current reference gives Promise<void>. Check the installed Puppeteer version and its matching API reference. In current code, use await fileChooser.cancel().

6. Reliability and runtime notes

  • Race safety: Start the event waiter and triggering action together. This avoids missing a fast chooser event.
  • Cleanup: Always resolve an intercepted chooser. In larger scripts, put cancellation in the normal control flow and close the browser in a finally block.
  • Timeouts: Use a finite waiter timeout so a page that stops triggering the expected control does not leave the script waiting indefinitely.
  • Runtime: Cancellation itself is a single browser protocol operation; most elapsed time comes from launching the browser, navigating, and triggering the page control. The research sources provide no benchmark figures.
  • Cost: Puppeteer is browser automation you run in your own environment. Account for your compute and browser infrastructure; there is no per-cancellation price specified by the cited API documentation.

7. Or skip the browser setup

If your goal is a screenshot rather than automating a file input, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. It does not require you to launch and manage a Puppeteer browser for the capture.

Cookie banners are accepted and removed before the shot, along with known newsletter popups and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers identify the page verdict and billing status. AI agents can use its MCP server tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Every feature is on every plan. See the ScreenshotNeo 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}`);
const data = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));

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

8. FAQ

Does canceling choose an empty file?

No. cancel() closes the chooser without selecting files.

Can I cancel a chooser that was already open before the waiter started?

No. The waiter needs to be registered before the page action launches the chooser.

Should I await cancel()?

Yes, for current Puppeteer versions the reference specifies a promise-returning method, so use await fileChooser.cancel().