Recommended Free Tools
Automate a browser upload by setting a test file on the page’s input[type="file"] through your framework, then submit the form and assert an observable result. This avoids trying to control the operating system’s file-picker dialog. The same pattern applies across Selenium, Playwright, and Cypress, although their APIs differ.
Build the test around the upload outcome
A file input accepting a value proves only that the browser automation selected a file. A useful end-to-end test follows the application’s normal flow through submission or processing and checks a result the product actually exposes: for example, a success message, uploaded filename, or newly created record.
As an Amazon Associate I earn from qualifying purchases.
- Keep a small, deterministic valid fixture with the test suite, or generate a file in memory where supported.
- Locate the underlying file input and provide the fixture through the framework’s upload API.
- Submit using the application’s normal control or workflow.
- Wait for a meaningful completion state, then assert it. Avoid treating a transient spinner or the selected input value as proof of success.
Use descriptive fixture names and avoid dependence on a developer’s Downloads folder or another machine-specific path. For remote browser execution, make sure the file is available to the browser session; a path that exists only on the test runner may not exist on the remote node.
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 →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Upload a file with Selenium WebDriver
Selenium’s documented method is to locate the file input and call sendKeys with the full path to a local fixture. It does not control the native upload dialog; setting the input directly avoids opening that dialog. See Selenium’s file upload documentation.
#1 Best Overall
from pathlib import Path
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
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()
uploaded_name = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, '[data-testid="uploaded-file-name"]'))
)
assert uploaded_name.text == "sample.pdf"
Replace the submit selector and result selector with elements your application actually provides. The example assumes a Python Selenium test, a fixture at the shown relative location, and an application that displays the uploaded filename in the indicated test element; adjust those to your project.
Remote Selenium sessions
With a remote browser or grid, confirm how the provider transfers a runner-local file to the browser node. BrowserStack documents a Selenium workflow using LocalFileDetector; see BrowserStack’s file upload documentation. The transfer mechanism is provider-specific.
Upload a file with Playwright
Use locator.setInputFiles() on the file input. Playwright supports file paths, arrays of files, directories, clearing the selection with an empty array, and in-memory file payloads. Its documentation also describes waiting for a filechooser event when the application creates the input in response to a click. See Playwright’s input documentation.
Rank #2
import { test, expect } from '@playwright/test';
import path from 'node:path';
test('uploads a document', async ({ page }) => {
await page.goto('/upload');
await page.locator('input[type="file"]').setInputFiles(
path.join(__dirname, 'fixtures', 'sample.pdf')
);
await page.getByRole('button', { name: 'Upload' }).click();
await expect(page.getByTestId('uploaded-file-name')).toHaveText('sample.pdf');
});
Use a label locator where the page’s accessible markup makes that a reliable way to identify the input. For a generated in-memory file, provide a payload with a name, MIME type, and buffer:
await page.locator('input[type="file"]').setInputFiles({
name: 'sample.txt',
mimeType: 'text/plain',
buffer: Buffer.from('test content')
});
To clear a selected file, pass an empty array to setInputFiles([]). If the input appears only after clicking an upload control, wait for the chooser event and set the file on the chooser rather than assuming an input was already present.
Upload a file with Cypress
Cypress uses selectFile() on the file input. It accepts fixture paths, arrays, typed arrays or buffers, and file metadata such as a filename and MIME type. For an example using a fixture path:
describe('file upload', () => {
it('uploads a document', () => {
cy.visit('/upload');
cy.get('input[type="file"]').selectFile('cypress/fixtures/sample.pdf');
cy.contains('button', 'Upload').click();
cy.get('[data-testid="uploaded-file-name"]').should('have.text', 'sample.pdf');
});
});
For an in-memory file, pass a file object with content and metadata; for example, Cypress documents use of typed arrays or buffers along with a filename and MIME type. If the intended interaction is a drop zone, use selectFile(..., { action: 'drag-drop' }) on the drop target. Hidden file inputs may require { force: true }; use it deliberately because it bypasses Cypress’s normal actionability checks. Cypress also specifies that selecting multiple files requires the input to have its multiple property. Refer to the current Cypress selectFile documentation.
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 errorsCover multiple files and empty selection
Test multiple selection only when the product supports it. The HTML multiple attribute allows an input to accept more than one file; without it, do not expect a multi-file selection to work. See MDN’s file input reference.
- In Playwright, pass an array of file paths or file payloads to
setInputFiles(). - In Cypress, pass an array to
selectFile(), and confirm the input has themultipleproperty. - In Selenium, select multiple files only if the application’s input and browser workflow support it; assert the expected count and verify every resulting file, not only the first displayed filename.
- For empty submission, exercise the application’s expected behavior when no file is selected and assert the corresponding validation or outcome.
Framework APIs are not identical. Choose the one already used by the suite unless a concrete requirement—such as in-memory fixtures, dynamic chooser handling, drag-and-drop, directory selection, or remote-grid transfer—makes a difference.
Rank #4
Test rejected uploads and security behavior
Do not treat client-side validation as the security boundary. OWASP’s WSTG 4.2 upload guidance frames the objective as: “Verify that the unwelcomed file types are rejected and handled safely.” Its checks include rejected file types, batch uploads, checks that rely only on JavaScript, request Content-Type or filename extension, direct access to uploaded files, script or code handling, and file-path handling. See the OWASP WSTG upload test.
Run security cases only in a test environment and define expected behavior from the application’s acceptance rules. Verify that a disallowed upload is rejected with a safe, useful result, rather than assuming a browser-side message means the server rejected it. Include batch behavior when relevant. If the application enforces documented size limits or asynchronous scanning, add tests around the product-specific boundary and assert the final error or processing state; the limit and state names depend on the application.
Troubleshoot common upload test failures
- The file chooser opens or the test hangs: target
input[type="file"]with the framework’s upload API instead of automating the operating system dialog. For a dynamically created Playwright input, wait for the file chooser event. - The file is not found: use a fixture path relative to the test project and resolve it as needed. In a remote session, configure the provider’s file transfer mechanism; the runner’s local path may not be available on the browser node.
- Multiple-file selection fails: verify that the application input supports multiple files. Cypress explicitly requires the input’s
multipleproperty. - Cypress says the input is not actionable: check whether it is hidden and whether the actual interaction is a drop-zone interaction. Use
{ force: true }only when intentionally bypassing actionability checks, or use drag-drop mode for the drop target. - The test passes after selection but the upload is broken: selection is not submission. Exercise the actual submit or processing path and assert the resulting UI state or record.
- A file with a disallowed extension is rejected in the UI but still accepted by the server: test server-side behavior and the application’s actual validation rules; client-side checks alone are not sufficient evidence of safe rejection.
Or skip the browser setup
For a website screenshot rather than an interactive upload test, ScreenshotNeo provides a one-request screenshot API. It does not replace a browser upload test: use the framework steps above to exercise file selection, submission, and application behavior. For a page capture, the cURL call is:
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 setup and options. Before a capture, it can accept cookie or consent banners and remove 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server offers screenshot, page-info, and PDF tools to AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Should I test uploads through the UI or only through the upload API?
A UI test verifies the browser-facing workflow, including file selection and the product’s visible result. API-level upload tests can complement it, but do not cover the main browser interaction described here.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Which framework should I use if I have not chosen one?
Prefer the framework already used by your project. If a specific need drives the decision, compare language and stack fit, generated-buffer support, dynamic file chooser handling, multiple-file or directory behavior, drag-and-drop support, locator model, and remote-grid file transfer.
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.




