To upload a photo with Python Selenium, locate the page’s real HTML <input type="file"> element and call send_keys() with the photo’s absolute path. Selenium sends the path directly to the control, so you do not automate the operating system’s file-picker window. You still must submit the page’s form and verify a visible result, such as the filename shown after upload.
What you need before writing the test
- Python and the Selenium package installed in the environment that will run the test.
- A browser supported by your Selenium setup.
- An image file that the browser-driving process can read.
- The URL of the upload page and the page’s actual locators for its file input, submit control and success message.
The example below uses a local file named photos/example.jpg. Replace the URL and selectors with those from your page. The IDs file-submit and uploaded-files are illustrative; they are not universal Selenium selectors.
The documented upload pattern
- Build an absolute path to the image.
- Locate the HTML file input, commonly with the CSS selector
input[type='file']. - Call
send_keys(absolute_path)on that element. - Click the site’s submit button or invoke its normal form action.
- Wait for and assert an outcome from the page.
Selenium’s official file-upload guidance uses this approach because WebDriver cannot operate the native file-upload dialog. Sending the path to the file input is the supported alternative.
A complete Python example
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
UPLOAD_PAGE = "https://example.com/upload"
PHOTO = os.path.abspath("photos/example.jpg")
if not os.path.isfile(PHOTO):
raise FileNotFoundError(f"Photo does not exist: {PHOTO}")
# Configure the browser according to your Selenium installation.
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 20)
try:
driver.get(UPLOAD_PAGE)
# Use the page's real locator if it differs from this common selector.
file_input = wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "input[type='file']")
)
)
file_input.send_keys(PHOTO)
submit = wait.until(
EC.element_to_be_clickable((By.ID, "file-submit"))
)
submit.click()
# Wait for the page to report what it accepted.
uploaded = wait.until(
EC.visibility_of_element_located((By.ID, "uploaded-files"))
)
uploaded_name = uploaded.text.strip()
expected_name = os.path.basename(PHOTO)
assert uploaded_name == expected_name, (
f"Expected {expected_name!r}, got {uploaded_name!r}"
)
print(f"Upload confirmed: {uploaded_name}")
finally:
driver.quit()
The assertion checks the filename returned by the page, not merely the fact that Selenium accepted a path. A page can still reject a file during validation, fail to submit, or display an error after the input has been populated.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →#1 Best Overall
Choosing and resolving the photo path
Prefer an absolute path
os.path.abspath() converts a project-relative path into a full path that is less sensitive to the process’s current working directory. Selenium’s Python API documentation recommends an operating-system-appropriate absolute path for cross-platform tests. You can use pathlib instead:
from pathlib import Path
photo = Path("photos/example.jpg").resolve()
file_input.send_keys(str(photo))
Check the file before opening the browser. This turns a confusing upload failure into an immediate, useful error. The process running Selenium must have permission to read the file. If you run under Cygwin, pay attention to the Windows path format expected by the browser-driving environment.
Do not send the path to a text field
Only the file input accepts a local file path through send_keys. Sending it to a normal text box changes text in that box; it does not attach a file. Inspect the page source or browser developer tools and identify the actual element whose markup resembles:
<input type="file" name="photo" accept="image/*">
If there are several file inputs, target the one belonging to the form you intend to submit. More specific locators are safer, for example form#profile-upload input[type='file'] or a stable name attribute.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #2
Submitting and confirming the form
Use the site’s normal submit action
Selecting a file does not necessarily send an HTTP request. Click the page’s submit button, call the form’s visible action, or trigger the control that the application uses after selection. Avoid inventing a second submission path in the test; use the same interaction a user would use.
Dynamic applications may update the page asynchronously. Wait for a success element, uploaded filename, thumbnail, progress completion, URL change or other page-specific result. A fixed sleep can finish too early or waste time; an explicit wait tied to the expected condition is generally more reliable.
Verify more than a filename when the application exposes it
A filename check confirms that the page reports the expected name. If the application provides additional signals, assert the ones that matter to your test: an image preview, a success status, a server-generated identifier, or the absence of a validation message. The exact response is site-specific, so do not assume that every uploader exposes the same text or element.
Common uploader variations
Hidden file inputs
Many interfaces hide the file input behind a styled “Choose photo” button. If the hidden element is still a real input[type='file'], locate that element and send the path to it. You do not need to make the native chooser appear. If the control is not an HTML file input at all, this documented method may not apply; inspect the page and follow the application’s actual upload mechanism.
Image filters and validation
The accept attribute, server-side rules, authentication, maximum size and permitted formats are controlled by the website. Selenium does not override those policies. Test with a valid image first, then add separate cases for rejected extensions, oversized files or missing permissions if those behaviors are part of your application.
Several photos
An input with the multiple attribute may accept several paths in one call, but the page must support multiple selection and the test should verify each result. If the site renders one input per row, locate and populate the intended input elements individually. The sources for this procedure establish the single-file pattern; multi-file behavior depends on the target page.
Local and remote browser execution
| Execution setup | Path you provide | Important check |
|---|---|---|
| Browser runs on the same machine as the Python process | An absolute path readable by that process | Confirm the file exists and permissions allow reading it. |
| Browser runs through a remote Selenium service | Not established by the documentation cited here | Verify how your chosen remote setup transfers local files before relying on this pattern. |
Do not assume that a path on your laptop is automatically visible to a browser running on another host. Remote file-transfer behavior depends on the Selenium service and configuration; the official material used for this guide does not prescribe a universal remote setup.
Troubleshooting checklist
NoSuchElementException for the file input
- The selector may be wrong, the control may be inside an iframe, or the page may not have finished rendering.
- Inspect the live DOM, wait for the element, and switch into the correct iframe when the page actually uses one.
- Prefer a stable
id,nameor form-scoped CSS selector over a brittle positional XPath.
ElementNotInteractableException or a rejected send_keys
- Confirm that you found an
input[type='file'], not a styled button or text field. - Check that the element belongs to the active document and that the page has completed its initial rendering.
- Do not open the operating-system chooser as a workaround for this documented Selenium pattern.
The file cannot be found
- Print the resolved path and test it with
os.path.isfile(). - Remember that relative paths are resolved from the process’s current working directory, which may differ between an IDE, a terminal and continuous integration.
- Use a path readable by the account running the test and pass the string form of a resolved
Path.
The click succeeds but no upload is confirmed
- The button may trigger an asynchronous request; wait for the page’s success condition rather than ending the test immediately.
- The site may have rejected the image because of size, format, authentication or application validation.
- Capture the visible error or inspect the page state so the test reports the application’s reason instead of only timing out.
The filename assertion fails
- The page may normalize names, display several files, or show a server-generated label.
- Read the exact element the application uses for confirmation and assert the appropriate value for that workflow.
- Do not treat a changed display name as proof that the upload failed without checking the page’s documented behavior.
Reliability and maintenance practices
- Keep file preparation separate from browser actions so a missing fixture fails before a long test begins.
- Use explicit waits for the input, submit control and success condition.
- Keep selectors close to the page contract and update them when the markup changes.
- Use small fixture images for ordinary tests, plus deliberate boundary cases for validation rules.
- Always close the driver in a
finallyblock so failed uploads do not leave browser processes running. - Log the resolved path, target URL and final page message, while avoiding secrets or private photo contents in logs.
Or skip the browser setup
If your actual goal is to capture a clean image or PDF of a page after an upload workflow, rather than automate a local photo selection, ScreenshotNeo provides a one-request screenshot API. It is not a replacement for submitting a file to your application; it is an option for capturing the resulting web page without maintaining a browser script.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
For the API parameters and response details, see the ScreenshotNeo documentation. A cURL request looks like this:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/upload-result -o shot.webp
The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com/upload-result"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/upload-result' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Before the capture, ScreenshotNeo accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and each response identifies the page verdict and billing result in headers. Its MCP server lets Claude, Cursor and other MCP clients call take_screenshot, get_page_info and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Can I automate the native file-picker window instead?
For an ordinary HTML file input, you should not need to. Sending the absolute path to that input is the documented Selenium workflow and avoids native-dialog automation.
Does setting the file input prove that the server accepted the photo?
No. The page still has to submit the form and report a successful result. Assert the application’s visible confirmation or error state.
Free tools Windows power users keep installed
One-click scans. No signup required.
Will the same path always work with a remote WebDriver?
Not necessarily. The browser host may not share your local filesystem. Confirm the file-transfer behavior of the remote Selenium service you use; no universal remote configuration is established here.
Best Value
Frequently Asked Questions
Can I automate the native file-picker window instead?
For an ordinary HTML file input, sending the absolute path with Selenium is the documented workflow and avoids native-dialog automation.
Does setting the file input prove that the server accepted the photo?
No. Submit the form and assert the page’s success or error state.
Will the same path always work with a remote WebDriver?
Not necessarily; verify how your remote Selenium service makes local files available to the browser host.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →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.

