How to Move Files In and Out of a Cloud Sandbox
Updated October 27, 2026 .md
Short answer: Use sbx scp for files and folders of any size, in either direction. From code, the SDK and MCP read and write single files up to 5 MiB, and the SDK downloads up to 50 MiB. Clone repos inside the sandbox with git, and pull files from a stopped sandbox's snapshot without resuming it.
Which method to use#
| Method | Direction | Best for | Limits |
|---|---|---|---|
sbx scp |
Both | Single files and whole folders, large files | No size cap from Sandboxer; limited by your bandwidth and the sandbox's disk |
rsync over the CLI tunnel |
Both | Syncing a folder again and again (sends only changes) | Same as scp |
SDK files.write / read / readBytes |
Both | Config, inputs and results from your code | 5 MiB per file (413 file_too_large above that) |
SDK files.download |
Out | Build artifacts and archives from code | 50 MiB per file |
MCP write_file / read_file |
Both | An agent moving text or small binaries (base64) | 5 MiB per file |
git clone inside the sandbox |
In | Source code, at the sandbox's own network speed | None from Sandboxer |
| Hosted port | Out | A download link for a browser or another machine | Anyone with the URL can fetch while it's hosted |
sbx snapshot pull |
Out | Getting files from a stopped sandbox without resuming it | Whole snapshot or one --path |
The files API and the SDK work on paths under /home/user or /tmp. Relative paths start at /home/user.
sbx scp: files and folders, both directions#
sbx scp runs your installed OpenSSH scp through the same authenticated tunnel as sbx ssh, so it works behind any firewall and needs no key setup. Use <sandbox-id>:/path as the remote side.
id=sb_yke1vvb5ca
# Upload a file and a folder (51 files)
sbx scp ./data.csv $id:/home/user/
sbx scp -r ./my-project $id:/home/user/
sbx exec $id "ls ~ && ls ~/my-project/src | wc -l"
# data.csv
# my-project
# 51
# Download a file and a folder
sbx scp $id:/home/user/out/results.tar.gz ./
sbx scp -r $id:/home/user/out/reports ./
ls reports
# r1.txt r2.txt r3.txtWhen both ends have tar, a recursive copy to a new directory is sent as one tar stream, which is much faster for many small files.
Large files go the same way. A 100 MiB file of random bytes took under 10 seconds from our test machine (one measured run on prod, 2026-10-27):
head -c 104857600 /dev/urandom > big.bin
time sbx scp ./big.bin $id:/tmp/
# real 0m9.575sYour own upload speed sets the pace, so expect a 1 GB file to take roughly ten times as long on the same connection.
rsync: sync a folder repeatedly#
For a folder you change and push again and again, rsync sends only what changed. sbx ssh-config prints an SSH config stanza for the pseudo-host *.sbx, so any OpenSSH tool can reach a sandbox by id. Append it to ~/.ssh/config with sbx ssh-config --install, then:
rsync -av ./my-project/ $id.sbx:my-project/
# sending incremental file list
# README.md
#
# sent 1,061 bytes received 42 bytes 441.20 bytes/secOnly README.md, the one file we edited, was sent. The same stanza works for VS Code Remote-SSH (sb_yke1vvb5ca.sbx).
SDK: read and write files from code#
The TypeScript SDK (npm i sandboxer-sdk) reads SANDBOXER_API_KEY from the environment. This script ran against a live sandbox:
import { Sandboxer } from "sandboxer-sdk";
import { readFileSync, writeFileSync } from "node:fs";
const sandbox = await Sandboxer.get("sb_yke1vvb5ca");
// Write text and bytes (parent directories are created)
await sandbox.files.write("inbox/config.json", JSON.stringify({ retries: 3 }));
await sandbox.files.write("inbox/data.csv", readFileSync("data.csv"));
// Read them back
console.log(await sandbox.files.read("inbox/config.json"));
const bytes = await sandbox.files.readBytes("inbox/data.csv");
console.log("data.csv:", bytes.length, "bytes");
// Download a larger artifact (up to 50 MiB)
const tarball = await sandbox.files.download("out/results.tar.gz");
writeFileSync("results.tar.gz", tarball);
console.log("results.tar.gz:", tarball.length, "bytes");{"retries":3}
data.csv: 24 bytes
results.tar.gz: 182 bytesThe Python SDK has the same calls: files.write, files.read, files.read_bytes and files.download.
What happens at the limits#
We tried each limit. Errors arrive as a SandboxerError with status and code:
write 6 MiB: 413 file_too_large Files may be at most 5 MiB; use scp for larger files.
readBytes 20 MiB: 413 file_too_large Files over 5 MiB: use GET /sandboxes/{sandboxId}/artifacts (50 MiB) or scp.
download 20 MiB: 20971520 bytes
download 60 MiB: 413 file_too_large Artifacts may be at most 50 MiB; use scp for larger files.So: up to 5 MiB, use read/write. Up to 50 MiB out, use download. Anything bigger, or anything going in over 5 MiB, use sbx scp.
MCP: files for an agent#
An agent connected to the Sandboxer MCP server gets write_file and read_file, each up to 5 MiB. Text is utf8 by default; pass "encoding": "base64" for binary. These are real results from the local sbx mcp server (each call also passed sandboxId, left out here):
{"name": "write_file", "arguments": {"path": "notes/todo.md", "content": "- ship the guide\n"}}
→ "Wrote 17 bytes to /home/user/notes/todo.md."
{"name": "write_file", "arguments": {"path": "notes/pixel.bin", "content": "AAEC/w==", "encoding": "base64"}}
→ "Wrote 4 bytes to /home/user/notes/pixel.bin."
{"name": "read_file", "arguments": {"path": "notes/pixel.bin", "encoding": "base64"}}
→ "AAEC/w=="Without sandboxId, the tools use the sandbox this MCP session created or used last.
git clone inside the sandbox#
Source code doesn't need to pass through your machine at all. Clone it from inside:
sbx exec $id --timeout 120 "git clone --depth 1 https://github.com/expressjs/express.git && du -sh express"
# Cloning into 'express'...
# 2.0M expressFor private GitHub repos, attach them to an environment with sbx env add-repo base acme/web --branch main. New sandboxes clone them into /home/user/<repo> with a token, so git push works too when the environment passes GitHub credentials.
Download through a hosted port#
To hand a file to a browser or another machine, serve it and host the port:
sbx exec $id --detach "cd out && python3 -m http.server 8000"
sbx host $id 8000 --public
# "url":"https://hidden-chief-hare-8000.box.sandboxer.com"
curl -sS -o results.tar.gz -w "HTTP %{http_code} %{size_download} bytes\n" \
https://hidden-chief-hare-8000.box.sandboxer.com/results.tar.gz
# HTTP 200 182 bytes
sbx host hide $id 8000 # take the URL down; the server keeps runningGive the server a second to start before the first request. Without --public the URL is private and carries a _token: treat it like a password. After sbx host hide, the same URL returned 404.
Get files from a stopped sandbox#
A stopped sandbox costs nothing, and you don't have to resume it to get files out. Every stop writes a snapshot. Find it, list it and pull just what you need:
sbx stop $id
sbx snapshot latest $id # "id":"46b816c3-…","trigger":"stop"
sbx snapshot tree 46b816c3-… --path out
# 9 B out/reports/r1.txt
# 9 B out/reports/r2.txt
# 9 B out/reports/r3.txt
# 182 B out/results.tar.gz
sbx snapshot pull 46b816c3-… --path my-project -o ./restore
# ✓ Pulled 52 files (373 B) into ./restoreLeave out --path to download the whole snapshot (home_user/ and docker/). Tree paths are relative to /home/user.
FAQ#
What is the largest file I can upload to a sandbox?#
sbx scp and rsync have no Sandboxer size limit; the sandbox's disk and your bandwidth are the limits. The SDK, the files API and MCP accept up to 5 MiB per file and return 413 file_too_large above that.
Can I upload binary files through MCP or the SDK?#
Yes. The SDK sends bytes as base64 for you when you pass a Uint8Array or Buffer. With MCP, pass "encoding": "base64" to write_file and read_file.
Can I download files without resuming a stopped sandbox?#
Yes. sbx snapshot latest <sandboxId> finds the snapshot the stop wrote, sbx snapshot tree <snapshotId> lists its files, and sbx snapshot pull <snapshotId> --path <folder> downloads them. The sandbox stays stopped and isn't billed.
Which paths can the files API reach?#
Paths that resolve under /home/user or /tmp. Relative paths start at /home/user. For anything else, use sbx scp or sbx exec.
Is there a file browser?#
Yes. The dashboard has a file browser with upload and download on every sandbox page.
Related#
More guides
For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.
For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.
The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.
If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.