How ego-browser Handles File Uploads with setInputFiles: A CDP Deep Dive

The setInputFiles helper in ego-browser uploads files to <input type="file"> elements by resolving selectors to Chrome DevTools Protocol (CDP) object IDs and invoking the native DOM.setFileInputFiles method.

The ego-browser package from the citrolabs/ego-lite repository enables agent scripts to automate complex browser interactions programmatically. When you need to upload files through web forms, the setInputFiles function provides a direct bridge between your agent code and the browser's file input mechanics, handling the entire workflow from selector resolution to CDP execution.

Architecture of the setInputFiles Helper

The setInputFiles implementation follows a layered architecture that separates the public API surface from the underlying CDP operations.

Public API Entry Point (src/helpers.ts)

The helper is exposed to agent scripts through the main helpers module. In src/helpers.ts at line 99, the function is re-exported from the driver files module:

// src/helpers.ts (line 99)
export { setInputFiles } from "./driver/files.js";

This export makes setInputFiles available in the helper context that agents receive during script execution.

Driver Implementation (src/driver/files.ts)

The actual upload logic resides in src/driver/files.ts (lines 4-15). The function accepts a selector and file path(s), then orchestrates the CDP interaction:

// src/driver/files.ts
/**
 * Set files on a file input.
 * @param {string} selector CSS selector / @ref / loc= / xpath= for an input[type=file].
 * @param {string|string[]} path Absolute file path or paths to upload.
 */
export async function setInputFiles(selector, path) {
  const files = Array.isArray(path) ? path : [path];
  await withHandle(selector, async ({ objectId, sessionId }) => {
    await cdp("DOM.setFileInputFiles", { files, objectId }, sessionId);
  });
}

The implementation uses array normalization to handle both single strings and arrays of paths uniformly before passing them to the Chrome DevTools Protocol.

How the Upload Works Under the Hood

The execution flow involves three critical components working in sequence to manipulate the browser's DOM directly.

Selector Resolution via withHandle

The withHandle utility from src/driver/element-ops.ts resolves the provided selector to a CDP objectId and sessionId. This function handles multiple selector formats including:

  • CSS selectors (input#resume)
  • Reference IDs (@123)
  • Location-based selectors (loc=css:#profile-pic)
  • XPath expressions (xpath=//input[@type='file'])

CDP Command Invocation

Once resolved, the function invokes cdp("DOM.setFileInputFiles", …) from src/cdp-eval.ts. This sends the native CDP command that updates the DOM node's files property directly, simulating a user file selection without requiring UI interaction.

The CDP call structure follows this pattern:

await cdp("DOM.setFileInputFiles", { 
  files: ['/absolute/path/to/file.pdf'], 
  objectId: 'node-object-id' 
}, sessionId);

When the command succeeds, the file input's files property reflects the uploaded files exactly as if a user had manually selected them through the browser's file picker.

Practical Code Examples

You can call setInputFiles anywhere within an ego-browser agent script. The function returns a Promise that resolves when the browser confirms the file list update.

Upload a single file using a CSS selector:

await setInputFiles('input#resume', '/home/user/documents/resume.pdf');

Upload multiple files to inputs supporting the multiple attribute:

await setInputFiles('#gallery-upload', [
  '/tmp/img1.png',
  '/tmp/img2.png',
  '/tmp/img3.png'
]);

Using alternative selector syntax supported by the withHandle utility:

// Reference-based selector
await setInputFiles('@123', '/var/data/report.csv');

// Location-based selector
await setInputFiles('loc=css:#profile-pic', '/pics/avatar.png');

Error Handling Behavior

Any errors originating from the CDP call—such as invalid file paths, non-existent DOM nodes, or elements that aren't file inputs—bubble up through the helper framework. These errors manifest as standard JavaScript exceptions that you can catch using standard try…catch blocks:

try {
  await setInputFiles('#upload', '/nonexistent/file.pdf');
} catch (error) {
  console.error('Upload failed:', error.message);
}

This error propagation ensures that agent scripts can implement robust retry logic or fallback behaviors when file operations fail.

Summary

  • Entry Point: setInputFiles is exported from src/helpers.ts (line 99) for use in agent scripts.
  • Core Logic: Implementation resides in src/driver/files.ts, utilizing withHandle from src/driver/element-ops.ts and CDP commands from src/cdp-eval.ts.
  • Selector Support: Accepts CSS, @ref, loc=, and xpath= selector formats, all resolved to CDP object IDs.
  • Protocol: Uses DOM.setFileInputFiles via Chrome DevTools Protocol to set absolute file paths directly on DOM nodes.
  • Input Types: Handles both single strings and arrays of absolute file paths for multiple file uploads.
  • Error Handling: CDP errors propagate as JavaScript exceptions for standard try/catch handling within agent scripts.

Frequently Asked Questions

What selector types does setInputFiles support?

The function supports CSS selectors, reference IDs prefixed with @ (like @123), location-based selectors using the loc= prefix, and XPath expressions using the xpath= prefix. The withHandle utility in src/driver/element-ops.ts normalizes these formats to CDP object IDs before execution.

Can setInputFiles handle multiple file uploads?

Yes. When the target <input type="file"> element has the multiple attribute, pass an array of absolute paths as the second argument. The function normalizes single strings into arrays internally, ensuring consistent handling regardless of whether you upload one file or many.

How does error handling work in setInputFiles?

Errors from the underlying CDP call—such as invalid selectors, non-existent files, or elements that aren't file inputs—propagate up through the helper framework as standard JavaScript exceptions. You can wrap calls in try…catch blocks to handle failures gracefully within your agent scripts.

Is setInputFiles used for file downloads as well?

No. While setInputFiles specifically handles uploads via DOM.setFileInputFiles, the ego-browser package handles downloads through different CDP mechanisms, typically via Page.setDownloadBehavior or network response interception. The setInputFiles function is exclusively for uploading files to <input type="file"> elements.

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 →