How to Upload Files in ego-browser Using the setInputFiles Helper

The setInputFiles helper lets you programmatically upload files to <input type="file"> elements by resolving element handles and injecting absolute file paths directly via Chrome DevTools Protocol (CDP).

The ego-browser package from the citrolabs/ego-lite repository provides this helper to automate file selection without interacting with OS-level file dialogs. By leveraging CDP's DOM.setFileInputFiles method, the helper directly attaches files to input elements, supporting single and multiple file uploads through various invocation patterns.

Where the Helper is Defined

The setInputFiles functionality spans several key files in the codebase. The public API is exported from src/helpers.ts at line 99, which makes the helper available to automation scripts. The actual implementation resides in src/driver/files.ts, where the function resolves element references and invokes the CDP command. Underlying element handle management is handled by utilities in src/driver/element-ops.ts, specifically the withHandle and resolveHandle functions that safely manage CDP object lifecycles.

How setInputFiles Works

The helper operates through a three-stage pipeline that bridges high-level JavaScript calls with low-level browser automation.

Element Resolution

First, setInputFiles receives a selector string—supporting CSS selectors, @ref syntax, or loc= patterns—and delegates to withHandle in src/driver/element-ops.ts. This utility calls resolveHandleresolveElementObjectId to obtain a CDP objectId for the target element, ensuring the handle is released after use to prevent memory leaks (see lines 45–51 in element-ops.ts).

CDP File Injection

With the objectId secured, the implementation in src/driver/files.ts (lines 11–13) invokes the Chrome DevTools Protocol:

await cdp("DOM.setFileInputFiles", { files, objectId }, sessionId);

The files parameter is an array of absolute file paths that the Chrome/Edge runtime reads directly from the host file system. This bypasses the need for synthetic click events or OS dialog interactions.

Result

After successful execution, the <input type="file"> element contains the specified files. You can then trigger form submission with a standard click() on a submit button or proceed with other form interactions.

Usage Patterns

The helper supports three distinct invocation styles, all accepting either a single string or an array of strings for file paths.

Global Helper Syntax

Call the exported helper directly with a selector and file path:

await setInputFiles('input[name="avatar"]', '/home/user/photo.png');

This style imports setInputFiles from src/helpers.ts and executes the upload immediately.

Locator Method Syntax

Use the locator proxy method for chainable interactions:

await page
  .locator('input[name="attachments"]')
  .setInputFiles(['/tmp/report.docx', '/tmp/image.png']);

This pattern, wired in src/helpers.ts (lines 77–78), forwards to the same underlying driver code while maintaining the fluent locator API.

Ref-based Syntax

Reference elements captured in previous snapshots using the @ref notation:

await setInputFiles('@42', '/var/data/config.json');

This approach skips re-querying the DOM by using the stored object reference from a prior snapshot.

Critical Requirements

Absolute paths required: The CDP runtime cannot resolve relative paths. Use path.resolve() in your script to convert relative paths to absolute ones before passing them to the helper.

File accessibility: The host process must have read permissions for the specified files. If the file is inaccessible, the CDP call throws a "file not found" error.

Multiple files: Pass an array of strings to upload several files simultaneously to inputs that accept multiple selections.

Code Examples

// Single file upload using the global helper
await setInputFiles('input[type="file"]#resume', '/home/user/Resume.pdf');

// Uploading multiple files via locator chain
const uploadBtn = page.locator('button#send');
await page
  .locator('input[name="attachments"]')
  .setInputFiles(['/tmp/report.docx', '/tmp/image.png']);
await uploadBtn.click();

// Using a previously saved ref (e.g., @23 from a snapshot)
await setInputFiles('@23', '/var/data/config.json');

Summary

  • setInputFiles is the primary helper for file uploads in ego-browser, exported from src/helpers.ts and implemented in src/driver/files.ts.
  • It uses CDP's DOM.setFileInputFiles to inject files directly into <input type="file"> elements without OS dialog interaction.
  • The helper requires absolute file paths and handles single or multiple files via string or array arguments.
  • Three invocation styles are supported: global helper, locator method, and ref-based addressing.
  • Element resolution is safely managed through withHandle utilities in src/driver/element-ops.ts to prevent handle leaks.

Frequently Asked Questions

What is the difference between setInputFiles and a normal click upload?

setInputFiles bypasses the browser's native file picker dialog by directly manipulating the input element's FileList through Chrome DevTools Protocol. This is more reliable than simulating clicks on file inputs, which would require complex OS-level automation to handle the system file dialog.

Can I use relative file paths with the ego-browser uploadFile helper?

No. The underlying CDP DOM.setFileInputFiles method requires absolute file paths. You must resolve relative paths using path.resolve() or __dirname concatenation before passing them to setInputFiles, otherwise the Chrome runtime will fail to locate the files.

How do I upload multiple files to a single input element?

Pass an array of absolute file paths as the second argument:

await setInputFiles('input[multiple]', ['/path/to/file1.pdf', '/path/to/file2.pdf']);

Ensure the input element has the multiple attribute; otherwise, the browser may only accept the first file in the array.

Why am I getting a "file not found" error when using setInputFiles?

This error occurs when the Chrome/Edge process running the automation cannot access the file at the specified absolute path. Verify that the file exists, the path is absolute (not relative), and the Node.js process has read permissions for that file location. Network paths or files inside restricted directories may also cause this error.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →