Recommended Free Tools
For a standard upload, use your browser automation framework’s file-input API rather than trying to control the operating system’s native file picker. For a download, capture the framework’s download event or use its configured download folder, and wait until the file is complete before checking it. In remote runs, first establish whether the file path belongs to the test runner or the browser machine.
Upload a file through the page’s file input
Most upload controls ultimately use an HTML input type="file". Locate that input and pass it a path—or, where supported, an in-memory file payload. The framework sets the selected file without requiring automation of the native picker dialog.
As an Amazon Associate I earn from qualifying purchases.
Playwright
Use Locator.setInputFiles. Relative paths resolve from the process’s current working directory. The API supports one or multiple paths, directories, clearing the selection with an empty array, and in-memory payloads with a filename, MIME type, and buffer. After selecting a file, trigger the page’s upload action if the application requires one.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesimport { test, expect } from '@playwright/test';
import path from 'node:path';
test('uploads a fixture', async ({ page }) => {
await page.goto('https://example.com/upload');
const file = path.resolve('tests/fixtures/sample.pdf');
await page.locator('input[type="file"]').setInputFiles(file);
await page.getByRole('button', { name: 'Upload' }).click();
await expect(page.getByText('Upload complete')).toBeVisible();
});
To select multiple files, pass an array of paths. To clear the selection, pass an empty array. To create a test file in memory, pass a file payload containing its name, mimeType, and buffer; this avoids maintaining a fixture on disk when the test only needs synthetic content. Use the binding’s documented payload shape for your language.
#1 Best Overall
If an input only appears after clicking a custom control, register for the chooser before the click, then set its files:
const chooserPromise = page.waitForEvent('filechooser');
await page.getByRole('button', { name: 'Choose file' }).click();
const chooser = await chooserPromise;
await chooser.setFiles('tests/fixtures/sample.pdf');
Waiting for the event before clicking matters: otherwise the chooser may open before the test is listening for it.
Selenium
Selenium’s WebDriver interface does not interact with the native file-upload dialog. Find the file input and send it the full path, then submit or activate the page’s upload control. Build the path from a fixture location known to the test project rather than a developer-specific path. Selenium’s official File Upload documentation demonstrates resolving an absolute path before calling send_keys; the page reports a last modification date of 2025-10-30.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
from pathlib import Path
from selenium.webdriver.common.by import By
fixture = Path(__file__).parent / "fixtures" / "sample.pdf"
file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
file_input.send_keys(str(fixture.resolve()))
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
The input can be visually hidden while still being the element the page uses for uploads. Locate the actual file input rather than assuming the visible button itself accepts a path.
Rank #2
Cypress
Use selectFile(path) with the file input. Cypress resolves paths relative to the project root. Trigger the upload control if the application separates file selection from submission.
cy.visit('/upload');
cy.get('input[type="file"]').selectFile('cypress/fixtures/sample.pdf');
cy.contains('button', 'Upload').click();
cy.contains('Upload complete').should('be.visible');
For a hidden input that the UI activates through a visible button, Cypress documents using force: true when actionability checks prevent selection:
cy.get('input[type="file"]').selectFile('cypress/fixtures/sample.pdf', { force: true });
See the official Cypress selectFile documentation for supported file selection options.
Handle custom upload controls and drag-and-drop
First determine how the control works. A custom-looking button may open a standard file chooser backed by an input; a drop zone may instead listen for drag-and-drop events. Use the matching framework operation, not the native dialog.
Rank #3
Playwright chooser
When clicking the control opens a chooser, use the event-first pattern shown above: start waiting for the file-chooser event, click, then set one or more files on the chooser. This is useful when the input is created or activated dynamically.
Cypress drag-and-drop
To simulate dropping a disk file onto a chosen DOM element, use selectFile with action: 'drag-drop':
cy.get('[data-testid="drop-zone"]').selectFile('cypress/fixtures/sample.pdf', {
action: 'drag-drop'
});
The default selection action is intended for a file input or connected label; the drag-drop action targets the drop zone. Confirm the application displays the expected response after the drop, such as the selected filename or upload status, rather than treating the simulated gesture alone as proof of success.
Playwright MCP
Playwright MCP provides a file-chooser operation that accepts absolute paths and supports one or multiple files. Its browser_drop operation is intended for drag-and-drop zones and accepts paths or MIME-typed data. File access is restricted to workspace roots by default, so a path outside those roots may not be available to the tool. Keep test fixtures in an accessible workspace or configure access according to the environment’s documented boundary.
Rank #4
Make file paths work in local and remote runs
A path is meaningful only on the machine that can read it. In a local browser run, the test runner and browser commonly share access to the same machine’s files. With a remote browser, Grid, or MCP tool, do not assume the path on the machine executing the test exists on the browser host.
- Keep fixtures in the project and construct paths from a known project-relative location.
- Check which machine owns the path: the test runner, remote browser host, or automation tool workspace.
- If the remote setup cannot see the runner’s file, use its supported transfer mechanism rather than passing a path that only exists locally.
For Selenium Remote WebDriver, Selenium documents a Local File Detector to bundle and transfer a client-side file so the remote driver can access it. Java requires explicit configuration of that detector; other bindings may provide one by default. The precise behavior depends on the binding and remote setup, so verify the relevant version’s documentation. Playwright MCP’s workspace-root restriction is a separate access boundary; it should not be assumed to match Selenium’s file-transfer behavior.
Capture and verify downloads
Do not assert on a downloaded file merely because the page’s download action was clicked. Capture or locate the output using the framework’s documented mechanism, wait for completion, then inspect the saved file or its contents.
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 →Playwright
Playwright emits a download event when an attachment download starts and provides a Download instance for file operations. Register for the event before the click, then save the file to a known destination using the API for your language binding. Wait for the save operation to complete before checking the file.
Best Value
const downloadPromise = page.waitForEvent('download');
await page.getByRole('link', { name: 'Download report' }).click();
const download = await downloadPromise;
await download.saveAs('test-output/report.pdf');
Cypress
Cypress places application downloads in its configured downloadsFolder, which defaults to cypress/downloads. Trigger the download, then read or assert on the resulting file from disk. If the project changes the configured folder, use that configured location rather than assuming the default.
Selenium Grid
For Grid downloads, enable managed download support and the session capability, then retrieve the listed file to the client. Selenium warns that the remote downloadable-file listing is an immediate snapshot: it does not wait for a download to finish. Poll or otherwise wait for completion using the supported workflow before treating the file list or retrieved file as final.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting common failures
- File chooser does not open or the event is missed: In Playwright, start waiting for the chooser before clicking the control. For a standard input, bypass the chooser and call
setInputFiles. - File input cannot be found: Inspect the page for the underlying
input[type="file"]; a visible button or drop zone may only activate it. If it is created dynamically, wait for it or use the framework’s chooser API. - Path not found: Check the framework’s path base—Playwright uses the current working directory for relative paths, while Cypress uses the project root. Resolve fixture paths from the test project and confirm the file exists on the machine that must read it.
- Remote session cannot access a local fixture: Transfer the file through the remote framework’s supported mechanism. For Selenium Remote WebDriver, check Local File Detector configuration, especially in Java.
- Hidden input is blocked by Cypress: Use the documented
force: trueoption when actionability checks prevent selecting the file. - Drag-and-drop test selects but does not upload: Confirm that the target is the application’s actual drop zone and use Cypress’s
action: 'drag-drop'rather than the default input-selection action. - Download assertion runs too early: Capture Playwright’s download event and await saving; read from Cypress’s configured download folder only after the file is available; for Selenium Grid, remember the file listing is not a completion wait.
Performance, reliability, and cost considerations
File automation itself does not establish a universal runtime or cost figure; the official framework documentation describes APIs and behavior rather than a measured benchmark. Keep fixtures small and deterministic when file size is not under test, and use an in-memory Playwright payload when a disk fixture is unnecessary. For downloads, make the test wait for the actual completed output rather than relying on a fixed delay or an immediate remote listing. These practices make the test’s dependencies explicit without implying a performance guarantee.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Or skip the browser setup
If the task is to capture a website rather than test its upload or download workflow, ScreenshotNeo is a website screenshot API and MCP server for developers. A single GET request returns a PNG, JPEG, WebP, or PDF. Its clean-shot flow accepts cookie or consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
For example, save a screenshot of a page as WebP:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo also provides an MCP server for AI agents, with tools including take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month with no card.
Frequently Asked Questions
Can I upload a file without opening the native file picker?
Yes. For a standard upload input, use the framework’s file API: Playwright’s setInputFiles, Selenium’s send_keys on the input, or Cypress’s selectFile.
Can a browser automation tool access any path on my computer?
No. Path access depends on the execution setup. Remote browsers may need files transferred from the test runner, and Playwright MCP restricts access to workspace roots by default.
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.




