Overview
How to upload, download, manage and work with files within an active session
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
1// Upload file to session environment2const file = fs.createReadStream("./steel.png");3const session = await client.sessions.create();4const uploadedFile = await client.sessions.files.upload(session.id, {5file: file, // or path in global files api or absolute url6});
List Files in a Session File System
1const files = await client.session.files.list(sessionId);2files.forEach(file => {3console.log(`${file.path} | Size: ${file.size} | Last Modified: ${file.lastModified}`);4});
Download Files from Session File System
1// Download a specific file from a session2const response = await client.sessions.files.download(sessionId, "path/to/file");3const fileBlob = await response.blob();45// Download all files as zip archive6const archiveResponse = await client.sessions.files.downloadArchive(sessionId);
Delete Files from Sessions File System
1// Delete a specific file from a session2const response = await client.sessions.files.delete(sessionId, "path/to/file");34// Delete all files in a session5const archiveResponse = await client.sessions.files.deleteAll(session.id);
Global Files API
Upload File to Global Storage
1const file = fs.createReadStream("./dataset.csv");2const globalFile = await client.files.upload({3file,4// path: "dataset.csv" // optional5});6console.log(globalFile.path); // dataset.csv78// Using the file from Global Files API in a session9const session = await client.sessions.create();10const uploadedFile = await client.sessions.files.upload(session.id, {11file: globalFile.path12});
List All Files
1const files = await client.files.list();2files.forEach(file => {3console.log(`${file.path} | Size: ${file.size} | Last Modified: ${file.lastModified}`);4});
Download Global File
1const response = await client.files.download(file.path); // dataset.csv2const fileBlob = await response.blob();
Delete Global File
1await client.files.delete(file.path);
Usage in Context
Set File Input Values
Reference uploaded files in file input elements using CDP (Chrome DevTools Protocol).
1// Create CDP session for advanced controls2const cdpSession = await currentContext.newCDPSession(page);3const document = await cdpSession.send("DOM.getDocument");45// Find the input element6const inputNode = await cdpSession.send("DOM.querySelector", {7nodeId: document.root.nodeId,8selector: "#file-input"9});1011// Set the uploaded file as input12await cdpSession.send("DOM.setFileInputFiles", {13files: [uploadedSessionFile.path],14nodeId: inputNode.nodeId,15});16
Standard Playwright/Puppeteer Upload
1// For simple/smaller file uploads,2// using standard automation library methods will look at local files3await 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.
1# Before agent main loop...23# Hook to extract downloaded files to local machine if necessary4async def step_hook_start(agent):5if os.environ.get("BROWSER_PROVIDER") == "steel":6await agent._check_and_update_downloads()7if agent.available_file_paths and len(agent.available_file_paths) > 0:8has_new_files = False9for file_path in agent.available_file_paths:10if file_path not in downloaded_files:11downloaded_files.append(file_path)12has_new_files = True13if has_new_files:14try:15extracted_files = await browser_service.extract_downloaded_files(DOWNLOAD_PATH)16logger.info(f"Extracted files: {extracted_files}")17except Exception as e:18logger.error(f"Failed to extract downloaded files: {e}")1920async def main():21try:22browser_session = Browser(cdp_url=cdp_url, downloads_path="/files")23await browser_session.connect()24await browser_session.cdp_client.send.Target.createBrowserContext()25browser_context_ids_return = await browser_session.cdp_client.send.Target.getBrowserContexts()26browser_context_ids = browser_context_ids_return['browserContextIds']27browser_context_id = browser_context_ids[0]28await browser_session.cdp_client.send.Browser.setDownloadBehavior(params={"behavior": "allow", "downloadPath": "/files", "eventsEnabled": True, "browserContextId": browser_context_id})29agent = Agent(task=TASK, llm=model, browser_session=browser_session)30agent.browser_session.browser_profile.downloads_path = LOCAL_DOWNLOAD_PATH31agent_results = await agent.run(32on_step_start=step_hook_start,33max_steps=534)35except Exception as e:36print(f"Error: {e}")37finally:38# Clean up resources39if session:40client.sessions.release(session.id)41print("Session released")42print("Done!")43# Rest of code...
Complete Example
End-to-end workflow demonstrating global file management and session file operations.
1import dotenv from "dotenv";2import fs from "fs";3import { chromium } from "playwright";4import Steel from "steel-sdk";56dotenv.config();78const client = new Steel({9steelAPIKey: process.env.STEEL_API_KEY,10});1112async function main() {13let session;14let browser;1516try {17// Upload dataset to global storage for reuse18const datasetFile = new File(19[fs.readFileSync("./data/stock-data.csv")],20"stock-data.csv",21{ type: "text/csv" }22);2324const globalFile = await client.files.upload({ file: datasetFile });25console.log(`Dataset uploaded to global storage: ${globalFile.id}`);2627// Create session and mount global file28session = await client.sessions.create();29console.log(`Session created: ${session.sessionViewerUrl}`);3031const sessionFile = await client.sessions.files.upload(session.id, {32file: globalFile.path33});3435// Connect browser and use the file36browser = await chromium.connectOverCDP(37`wss://connect.steel.dev?apiKey=${process.env.STEEL_API_KEY}&sessionId=${session.id}`38);3940const currentContext = browser.contexts()[0];41const page = currentContext.pages()[0];4243// Navigate to data visualization tool44await page.goto("<https://www.csvplot.com/>");4546// Upload file to web application using CDP47const cdpSession = await currentContext.newCDPSession(page);48const document = await cdpSession.send("DOM.getDocument");49const inputNode = await cdpSession.send("DOM.querySelector", {50nodeId: document.root.nodeId,51selector: "#load-file",52});5354await cdpSession.send("DOM.setFileInputFiles", {55files: [sessionFile.path],56nodeId: inputNode.nodeId,57});5859// Wait for visualization and capture60await page.waitForSelector("svg.main-svg");6162// Download all session files (original upload + any generated files)63const archiveResponse = await client.sessions.files.download.archive(session.id);64const zipBlob = await archiveResponse.blob();6566// Files are automatically available in global storage after session ends6768} catch (error) {69console.error("Error:", error);70} finally {71if (browser) await browser.close();72if (session) await client.sessions.release(session.id);7374// List all available files in global storage75const allFiles = await client.files.list();76console.log(`Total files in storage: ${allFiles.length}`);77}78}7980main();
Reach out to us on the #help channel on Discord under the ⭐ community section.