# Managing Sandbox Files — Upload and download files and directories.


> *Render Sandboxes is in public beta.*
>
> APIs, defaults, and limits might change during the beta period.

After you [create a sandbox](sandboxes-creating), you can upload files and directories to it and download files it produces. Use these operations to provide code and input data, then retrieve results after [executing commands](sandboxes-executing).

## Sandbox paths

When specifying a path inside a sandbox:

- *Relative paths* resolve from the sandbox's home directory. For example, `main.py` refers to a file in that directory.
- *Absolute paths* resolve from the sandbox's filesystem root. For example, `/tmp/output.json` refers to a file in `/tmp`.

Commands also start in the sandbox's home directory, so a file uploaded to `main.py` is available to a command like `python main.py`.

## Uploading a file

The following example uploads a local file named `main.py` to the sandbox's home directory:

**Tab: CLI**

```shell
render sandboxes copy ./main.py sbx-abc123:main.py
```

Call [`render sandboxes copy`](sandboxes-cli-reference#sandboxes-copy) with the source and destination paths. Prefix the sandbox path with the sandbox's ID and a colon (`:`). You can also use `cp` as an alias for `copy`.

**Tab: TypeScript**

```typescript
import { readFile } from 'node:fs/promises'
import { Render } from '@renderinc/sdk'

const sandboxes = new Render().sandboxes
const sandboxId = 'sbx-abc123'

const data = await readFile('./main.py')
await sandboxes.upload(sandboxId, 'main.py', data)
```

Call [`sandboxes.upload`](sandboxes-sdk-typescript#upload) with the sandbox's ID, the destination path, and the file's contents. The contents can be a string, a `Buffer`, a `Uint8Array`, or a readable stream.

**Tab: Python (sync)**

```python
from render import Render

sandboxes = Render().sandboxes
sandbox_id = "sbx-abc123"

sandboxes.copy_to(sandbox_id, "./main.py", "main.py")
```

Call [`sandboxes.copy_to`](sandboxes-sdk-python#copy-to) with the sandbox's ID, the local source path, and the destination path inside the sandbox.

**Tab: Python (async)**

```python
import asyncio
from render import RenderAsync

async def main():
    sandboxes = RenderAsync().sandboxes
    sandbox_id = "sbx-abc123"

    await sandboxes.copy_to(sandbox_id, "./main.py", "main.py")

asyncio.run(main())
```

Call [`sandboxes.copy_to`](sandboxes-sdk-python#copy-to) with the sandbox's ID, the local source path, and the destination path inside the sandbox.

For a single file, provide the full destination path, including the filename. Uploading to an existing file replaces its contents.

## Downloading a file

The following example downloads a file named `output.json` from the sandbox's home directory:

**Tab: CLI**

```shell
render sandboxes copy sbx-abc123:output.json ./output.json
```

Reverse the source and destination order to download a file. If the local destination is an existing directory, the file is saved inside it with its original filename.

**Tab: TypeScript**

```typescript
import { writeFile } from 'node:fs/promises'

const download = await sandboxes.download(sandboxId, 'output.json')
await writeFile('./output.json', download.data)
```

Call [`sandboxes.download`](sandboxes-sdk-typescript#download) with the sandbox's ID and the source path. The method returns an object with the file's contents in `data`, its size in `size`, and its content type in `contentType`.

The SDK loads the entire download into memory. Use `writeFile` to save the returned buffer to your local filesystem.

**Tab: Python (sync)**

```python
local_path = sandboxes.copy_from(sandbox_id, "output.json", "./output.json")
print(local_path)
```

Call [`sandboxes.copy_from`](sandboxes-sdk-python#copy-from) with the sandbox's ID, the source path inside the sandbox, and the local destination path. The method saves the file and returns the local path it wrote.

If the local destination is an existing directory, the file is saved inside it with its original filename.

**Tab: Python (async)**

```python
local_path = await sandboxes.copy_from(sandbox_id, "output.json", "./output.json")
print(local_path)
```

Call [`sandboxes.copy_from`](sandboxes-sdk-python#copy-from) with the sandbox's ID, the source path inside the sandbox, and the local destination path. The method saves the file and returns the local path it wrote.

If the local destination is an existing directory, the file is saved inside it with its original filename.

## Transferring directories

You can transfer an entire directory, including its subdirectories. The directory's contents are placed directly inside the destination directory.

For example, if you upload the local directory `./src` to your sandbox's `./app` directory, a local file at `./src/main.py` is uploaded to `./app/main.py` inside the sandbox (not `./app/src/main.py`).

### Uploading a directory

The following example uploads the contents of a local `src` directory to a `src` directory inside the sandbox:

**Tab: CLI**

```shell
render sandboxes copy ./src sbx-abc123:src
```

Provide a local directory as the source path. The CLI transfers its contents automatically. No recursive flag is required.

**Tab: TypeScript**

First, create a tar archive of the directory's contents on your local machine:

```shell
tar -cf src.tar -C ./src .
```

Then upload the archive with `contentType` set to `application/x-tar`. The sandbox extracts its contents into the destination directory:

```typescript
import { createReadStream } from 'node:fs'

await sandboxes.upload(
  sandboxId,
  'src',
  createReadStream('./src.tar'),
  undefined,
  { contentType: 'application/x-tar' }
)
```

The `undefined` parameter leaves the optional workspace ID unset so you can provide the upload options as the fifth parameter.

**Tab: Python (sync)**

```python
sandboxes.copy_to(sandbox_id, "./src", "src")
```

Provide a local directory as the source path. The SDK archives its contents and extracts them into the destination directory automatically.

**Tab: Python (async)**

```python
await sandboxes.copy_to(sandbox_id, "./src", "src")
```

Provide a local directory as the source path. The SDK archives its contents and extracts them into the destination directory automatically.

### Downloading a directory

The following example downloads the contents of an `output` directory from the sandbox:

**Tab: CLI**

```shell
render sandboxes copy sbx-abc123:output ./output
```

The CLI creates the local destination directory if needed and extracts the downloaded contents into it.

**Tab: TypeScript**

Downloading a directory returns its contents as a tar archive. Save the archive to your local filesystem:

```typescript
const download = await sandboxes.download(sandboxId, 'output')
await writeFile('./output.tar', download.data)
```

Then extract it on your local machine:

```shell
mkdir -p ./output
tar -xf output.tar -C ./output
```

**Tab: Python (sync)**

```python
local_path = sandboxes.copy_from(sandbox_id, "output", "./output")
print(local_path)
```

The SDK creates the local destination directory if needed and extracts the downloaded contents into it.

**Tab: Python (async)**

```python
local_path = await sandboxes.copy_from(sandbox_id, "output", "./output")
print(local_path)
```

The SDK creates the local destination directory if needed and extracts the downloaded contents into it.

## Preserving files

A sandbox keeps its files between commands and while suspended. When the sandbox terminates, its filesystem is deleted.

Download any files you need before termination. To reuse the sandbox's filesystem in new sandboxes, [capture a snapshot](sandboxes-snapshots).