Skip to content

import Image from 'next/image'

Steel provides two complementary file management systems: Session Files for working with files within active browser sessions, and Global Files for persistent file storage across your organization.

Overview

Steel's file management system makes it easy to work with files in your automated workflows:

  • Session-Based File Operations: Upload files to active sessions for immediate use in browser automations, download files acquired during browsing

  • Persistent File Storage: Maintain a global file repository for reuse across multiple sessions and workflows

  • Workspace Management: Organize and access files generated across different automation runs

  • Data Pipeline Integration: Upload datasets once and reference them across multiple automation sessions

  • File Archival: Automatically preserve files from completed sessions for later access

How It Works

Session Files System

Files uploaded to active sessions become available within that session's isolated VM environment. These files can be used immediately with web applications and browser automation tools. When files are downloaded from the internet during a session, they become accessible through the same API. Session files persist beyond session lifecycle - files are automatically backed up when sessions end.

Global Files System

The Global Files API provides persistent, organization-wide file storage independent of browser sessions. Files uploaded to global storage can be referenced and mounted in any session. All session files are automatically promoted to global storage when sessions are released, creating a comprehensive file workspace.

Session Files API

This section outlines how to interact with the filesystem inside of the VM that your session is running from. All of these files are accessible from the browser.

Upload Files to Session File System

List Files in a Session File System

Download Files from Session File System

For raw HTTP requests, the {path} parameter is relative. Session file responses currently come back in a /files/... form, so strip that prefix before interpolating the value into the URL.

Delete Files from Sessions File System

The raw HTTP delete endpoint also expects the relative path segment rather than the /files/... form returned by session file responses.

Global Files API

Upload File to Global Storage

List All Files

Download Global File

For raw HTTP requests, pass a relative {path} value here as well.

Delete Global File

The raw HTTP delete endpoint expects the same relative {path} format used by the download endpoint.

Usage in Context

Set File Input Values

Reference uploaded files in file input elements using CDP (Chrome DevTools Protocol).

typescript
// Create CDP session for advanced controls
const cdpSession = await currentContext.newCDPSession(page);
const document = await cdpSession.send("DOM.getDocument");

// Find the input element
const inputNode = await cdpSession.send("DOM.querySelector", {
  nodeId: document.root.nodeId,
  selector: "#file-input"
});

// Set the uploaded file as input
await cdpSession.send("DOM.setFileInputFiles", {
  files: [uploadedSessionFile.path],
  nodeId: inputNode.nodeId,
});

Standard Playwright/Puppeteer Upload

typescript
// For simple/smaller file uploads,
// using standard automation library methods will look at local files
await page.setInputFiles("#file-input", [uploadedSessionFile.path]);

Browser-Use Example

Browser-use needs some setup before it can be used. This includes setting up the browser profile with the correct downloads path and adding in a step hook to extract downloaded files to your local machine if necessary.

python
# Before agent main loop...

# Hook to extract downloaded files to local machine if necessary
async def step_hook_start(agent):
    if os.environ.get("BROWSER_PROVIDER") == "steel":
        await agent._check_and_update_downloads()
        if agent.available_file_paths and len(agent.available_file_paths) > 0:
            has_new_files = False
            for file_path in agent.available_file_paths:
                if file_path not in downloaded_files:
                    downloaded_files.append(file_path)
                    has_new_files = True
            if has_new_files:
                try:
                    extracted_files = await browser_service.extract_downloaded_files(DOWNLOAD_PATH)
                    logger.info(f"Extracted files: {extracted_files}")
                except Exception as e:
                    logger.error(f"Failed to extract downloaded files: {e}")

async def main():
    try:
        browser_session = Browser(cdp_url=cdp_url, downloads_path="/files")
        await browser_session.connect()
        await browser_session.cdp_client.send.Target.createBrowserContext()
        browser_context_ids_return = await browser_session.cdp_client.send.Target.getBrowserContexts()
        browser_context_ids = browser_context_ids_return['browserContextIds']
        browser_context_id = browser_context_ids[0]
        await browser_session.cdp_client.send.Browser.setDownloadBehavior(params={"behavior": "allow", "downloadPath": "/files", "eventsEnabled": True, "browserContextId": browser_context_id})
        agent = Agent(task=TASK, llm=model, browser_session=browser_session)
        agent.browser_session.browser_profile.downloads_path = LOCAL_DOWNLOAD_PATH
        agent_results = await agent.run(
            on_step_start=step_hook_start,
            max_steps=5
        )
    except Exception as e:
        print(f"Error: {e}")
    finally:
        # Clean up resources
        if session:
            client.sessions.release(session.id)
            print("Session released")
        print("Done!")
# Rest of code...

Complete Example

End-to-end workflow demonstrating global file management and session file operations.

typescript
import dotenv from "dotenv";
import fs from "fs";
import { chromium } from "playwright";
import Steel from "steel-sdk";

dotenv.config();

const client = new Steel({
  steelAPIKey: process.env.STEEL_API_KEY,
});

async function main() {
  let session;
  let browser;

  try {
    // Upload dataset to global storage for reuse
    const datasetFile = new File(
      [fs.readFileSync("./data/stock-data.csv")],
      "stock-data.csv",
      { type: "text/csv" }
    );

    const globalFile = await client.files.upload({ file: datasetFile });
    console.log(`Dataset uploaded to global storage: ${globalFile.path}`);

    // Create session and mount global file
    session = await client.sessions.create();
    console.log(`Session created: ${session.sessionViewerUrl}`);

    const sessionFile = await client.sessions.files.upload(session.id, {
      file: globalFile.path
    });

    // Connect browser and use the file
    browser = await chromium.connectOverCDP(
      `wss://connect.steel.dev?apiKey=${process.env.STEEL_API_KEY}&sessionId=${session.id}`
    );

    const currentContext = browser.contexts()[0];
    const page = currentContext.pages()[0];

    // Navigate to data visualization tool
    await page.goto('https://www.csvplot.com/');

    // Upload file to web application using CDP
    const cdpSession = await currentContext.newCDPSession(page);
    const document = await cdpSession.send("DOM.getDocument");
    const inputNode = await cdpSession.send("DOM.querySelector", {
      nodeId: document.root.nodeId,
      selector: "#load-file",
    });

    await cdpSession.send("DOM.setFileInputFiles", {
      files: [sessionFile.path],
      nodeId: inputNode.nodeId,
    });

    // Wait for visualization and capture
    await page.waitForSelector("svg.main-svg");

    // Download all session files (original upload + any generated files)
    const archiveResponse = await client.sessions.files.downloadArchive(session.id);
    const zipBlob = await archiveResponse.blob();

    // Files are automatically available in global storage after session ends

  } catch (error) {
    console.error("Error:", error);
  } finally {
    if (browser) await browser.close();
    if (session) await client.sessions.release(session.id);

    // List all available files in global storage
    const allFiles = await client.files.list();
    console.log(`Total files in storage: ${allFiles.data.length}`);
  }
}

main();

:::callout type: help

Need help building with the Files API?

Reach out to us on the #help channel on Discord under the ⭐ community section. :::

SOP Documentation Hub - Built from Steel.dev Official Docs