In Selenium, how do you upload a local file through an input type=file element on a page?
answer
- The dialog is not part of the page
- Do not click the input
- Text goes straight to the element
- Absolute path, not relative
- sendKeys on the input itself
basics
~10 sFind the input type=file element and send it the file's absolute path with sendKeys. Selenium sets the file directly on the input and never opens or drives the operating system's file-chooser dialog.
solid answer
~40 sLocate the `<input type="file">` element and call `sendKeys` on it with an absolute path to the file. Under the W3C Element Send Keys command a file input is a special case: rather than synthesising keystrokes, the remote end verifies the file exists, sets the element's selected files, and fires `input` and `change`, so the page reacts exactly as it would for a real user. Never try to click the input to open the chooser - clicking an `<input type="file">` is defined to fail with `invalid argument`, surfaced in Java as `InvalidArgumentException`, because the native dialog lives outside the document and WebDriver cannot reach it. For an input carrying `multiple`, join several absolute paths with a newline; more than one path without that attribute is an `invalid argument` error.
code
java · 20 linesimport java.nio.file.Path;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class LeafPhotoUpload {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
try {
driver.get("https://garden-centre.example/plant-finder");
Path photo = Path.of("src/test/resources/fern-leaf.jpg").toAbsolutePath();
WebElement input = driver.findElement(By.cssSelector("input#leaf-photo[type=file]"));
input.sendKeys(photo.toString());
driver.findElement(By.id("identify-plant")).click();
} finally {
driver.quit();
}
}
}go deeper
Be ready to say that the path goes to the input element via sendKeys and that the operating system dialog is never driven. Knowing the path must be absolute is the other half of the expected answer.
Explain what the remote end actually does with the text: it verifies the file exists, sets the element's selected files, and fires input and change rather than typing anything. Mention the newline separator for a multiple input.
Show you know why clicking the input is a defined failure rather than merely unsupported, and be able to diagnose the common reports: a path that does not resolve, a second path on an input without multiple, and a form that was never submitted.
Own the rule that a screen-driven upload must not depend on anything outside the browser. Argue why an approach that reaches for a desktop automation tool to drive the chooser is a design you would reject rather than debug.
## Why the native file chooser is off limits For a human, an upload starts by clicking an `<input type="file">` and picking a file in a **native file-chooser dialog** drawn by the operating system. That dialog is not part of the page, not part of the DOM, and not part of any browsing context, so a WebDriver remote end - which drives a document - has no handle on it at all. No locator reaches it and no wait can see it. The W3C WebDriver specification does not leave this to chance. The **Element Click** command opens with an explicit guard: if the element is an `input` element in the *file upload state*, return the error `invalid argument`. Selenium 4's Java binding surfaces that as `InvalidArgumentException`. Clicking the input is not a slow path or an unsupported path - it is a defined failure, and the specification wrote it that way precisely so nobody builds a test on a dialog the protocol cannot reach. ## What Element Send Keys does with a file input The upload rides on **Element Send Keys** instead - `WebElement.sendKeys(CharSequence...)` - which treats a file input as a special case rather than as somewhere to type. The remote end steps run in this order: 1. Decide whether the element is an `input` in the file upload state. 2. If it is, skip the usual scroll-into-view and keyboard-interactability checks. (The `strictFileInteractability` capability is what puts those checks back.) 3. Split the supplied text on the newline character into a list of paths. 4. Fail with `invalid argument` if the list is empty, or if it holds more than one path while the element carries no `multiple` attribute. 5. Verify that every named file exists; if any does not, return `invalid argument`. 6. Set the element's selected files, then fire `input` and `change` on the element. Because the remote end fires `input` and `change`, an application that renders a filename preview, enables a submit button from a change listener, or kicks off a client-side size check behaves exactly as it would for a real customer. No keystroke is ever synthesised, and no `Keys.ENTER` is needed to "confirm" anything. ## The command-by-command picture | What you write | What actually happens | |---|---| | `input.click()` | `invalid argument` - the specification refuses to open the native dialog | | `input.sendKeys("/abs/leaf.jpg")` | the file is attached and `input` plus `change` fire | | `input.sendKeys("/abs/a.jpg\n/abs/b.jpg")` on a `multiple` input | both files attach, appended to the selection | | the same two paths without `multiple` | `invalid argument`, and nothing attaches | | `input.clear()` | the current selection is emptied | ## Why the path has to be absolute - The path is verified and opened by the **browser process**, never by your test runner, so it is resolved against the browser's working directory rather than yours. - A path such as `fixtures/fern-leaf.jpg` therefore usually names nothing at all, and the call fails with `invalid argument` rather than uploading the wrong file. - Build the string from your fixture's real location - `Path.toAbsolutePath()` in Java, `File.getAbsolutePath()` on a `File` - so the test does not depend on where the runner was launched. - Let the platform supply its own separators rather than hand-writing them; `Path.toString()` already does. ## A garden-centre plant finder, end to end ```java Path photo = Path.of("src/test/resources/fern-leaf.jpg").toAbsolutePath(); WebElement input = driver.findElement(By.cssSelector("input#leaf-photo[type=file]")); input.sendKeys(photo.toString()); driver.findElement(By.id("identify-plant")).click(); ``` The customer's leaf photo is attached to the plant finder's input, the page's own change listener enables the *Identify plant* button, and the test clicks that button - a normal element, in the document, that WebDriver can drive. ## What still goes wrong - **Locating the wrong element.** Styled uploaders wrap the real input in a label or a button; send the path to the `input`, not to its pretty wrapper, or the text is typed nowhere useful. - **Adding a submit keystroke.** Appending `Keys.ENTER` to the path makes it part of the filename and breaks the existence check. - **Assuming the file was posted.** `sendKeys` only selects the file; the form still has to be submitted by whatever control the page uses. - **Reaching for a scripted workaround.** Un-hiding an input or synthesising a drop is unnecessary here - the send-keys path already bypasses visibility for file inputs by default.
- The upload control on the page is a styled button, and the real input is hidden behind it. Does that change anything?Not by default. Element Send Keys skips the scroll-into-view and interactability checks for a file input unless the session sets `strictFileInteractability` to true, so a hidden or zero-size input accepts the path. Locate the `input` element itself rather than the styled button, since the button is not the element the path belongs to.
- How would you attach two plant photos at once?Join the absolute paths with a newline character and send the whole string in one `sendKeys` call. This only works when the input carries the `multiple` attribute; without it, the remote end rejects a list of more than one path with `invalid argument` and attaches nothing. With `multiple`, the files are appended to the element's existing selection.
- How do you clear a file the test already attached?Call `clear()` on the same input element. It empties the element's selected files, and reading the element's value back afterwards returns an empty string. There is no need to reload the page or re-find the element just to reset the selection.
saying these in an interview costs you the question
- Clicking the file input to open the native chooser dialog
- Automating the operating system dialog with a separate desktop tool
- Sending a path relative to the test runner's working directory
- Appending Keys.ENTER to the path to confirm the selection
- Sending the path to the styled button instead of the input element