Working with Files in Sessions
How to manage and work with files within an active session
The Steel Files API provides a files
endpoint that allows you to manage files within active browser sessions. This guide explains how to manage files—from uploading and using them in your browser session to downloading them back to your machine.
For additional practical examples and recipes, check out the Steel Cookbook.
PrerequisitesCopied!
-
Steel API Key
-
Steel SDK installed (`npm install steel-sdk`)
-
Familiarity with Steel sessions
Uploading Files to a SessionCopied!
Small Files
To upload a file from your local machine onto a page, you can use existing puppeteer/playwright methods. You simply pass in the local path where your file is stored and it should do upload direct to the page.
await page.goto("https://website.com/");
await page.setInputFiles("#load-file", PATH_TO_FILE);
Larger Files (more stable)
To upload larger files from your local machine into an active Steel session, you can use the client.sessions.files.upload
method. You need to provide the sessionId
and a File
object. The method returns details about the uploaded file, crucially including its path
within the session's environment.
const file = new File(["Hello World!"], "hello.txt", { type: "text/plain" });
const uploadedFile = await client.sessions.files.upload(session.id, { file });
Once uploaded, you can reference the file using the uploadedFile.path
returned by the upload method.
Using Uploaded Files within a SessionCopied!
After uploading the file to that session, you need to pass in some slightly custom code to get it to point to the directory within the VM, instead of the way we did it above (which would by default point to your local machine):
// Create a CDP session to pass in some custom controls
const cdpSession = await currentContext.newCDPSession(page);
const document = await cdpSession.send("DOM.getDocument");
// We need to find the input element using the selector
const inputNode = await cdpSession.send("DOM.querySelector", {
nodeId: document.root.nodeId,
selector: "#load-file", //ID for the input element
});
// Set the CSV file as input on the page.
await cdpSession.send("DOM.setFileInputFiles", {
files: [uploadedFile.path],
nodeId: inputNode.nodeId,
}
Downloading FilesCopied!
To download a file from a Steel session back to your local machine, you can use the client.sessions.files.download
method:
const response = await client.sessions.files.download(session.id, file.id);
const downloadedFile = await response.blob();
Complete Example (Playwright, Node.js)Copied!
Below is a full script that demonstrates the complete workflow. The script creates a Steel session, uploads a CSV file, uses it on a webpage, and then captures a screenshot of rendered content—all driven by Playwright.
import dotenv from "dotenv";
import fs from "fs";
import { chromium } from "playwright";
import Steel from "steel-sdk";
dotenv.config();
const STEEL_API_KEY = process.env.STEEL_API_KEY;
// Initialize Steel client with the API key from environment variables
const client = new Steel({
steelAPIKey: STEEL_API_KEY,
});
async function main() {
let session;
let browser;
try {
console.log("Creating Steel session...");
// Create a new Steel session with available options
session = await client.sessions.create({ /* Custom options here */});
console.log(
`Steel Session created!\nView session at ${session.sessionViewerUrl}`
);
// Read the CSV file from the local file system
const file = new File(
[fs.readFileSync("./assets/stock.csv")],
"stock.csv",
{
type: "text/csv",
}
);
// Upload CSV file to the Steel session
const uploadedFile = await client.sessions.files.upload(session.id, {
file,
});
console.log(
`CSV file uploaded successfully!\nFile path on Steel session: ${uploadedFile.path}`
);
// Connect Playwright to the Steel session
browser = await chromium.connectOverCDP(
`wss://connect.steel.dev?apiKey=${STEEL_API_KEY}&sessionId=${session.id}`
);
console.log("Connected to browser via Playwright");
// Use the existing browser context to ensure session recording
const currentContext = browser.contexts()[0];
const page = currentContext.pages()[0];
// ============================================================
// Your Automations Go Here!
// ============================================================
// Navigate to the CSV plotting website and wait for the page to load
await page.goto("https://www.csvplot.com/");
// Create a CDP session to pass in some custom controls
const cdpSession = await currentContext.newCDPSession(page);
const document = await cdpSession.send("DOM.getDocument");
// We need to find the input element using the selector
const inputNode = await cdpSession.send("DOM.querySelector", {
nodeId: document.root.nodeId,
selector: "#load-file",
});
// Set the CSV file as input on the page.
await cdpSession.send("DOM.setFileInputFiles", {
files: [uploadedFile.path],
nodeId: inputNode.nodeId,
});
// Wait for the rendered SVG, scroll it into view, and capture a screenshot
const svg = await page.waitForSelector("svg.main-svg");
await svg.scrollIntoViewIfNeeded();
await svg.screenshot({ path: "stock.png" });
// ============================================================
// End of Automations
// ============================================================
} catch (error) {
console.error("An error occurred:", error);
} finally {
// Cleanup: Gracefully close the browser and release the session when done
if (browser) {
await browser.close();
console.log("Browser closed");
}
if (session) {
console.log("Releasing session...");
await client.sessions.release(session.id);
console.log("Session released");
}
console.log("Done!");
}
}
// Run the script
main();