> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lazycloud.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Artifacts

> Files a task produces, kept after the container stops for download or sharing through expiring public URLs.

Artifacts expire with your plan's retention window, so files you need for
longer belong in a [volume](/concepts/volumes).

## Save one

Save this as `report.py`. The task writes a CSV and returns a download URL:

```python theme={null}
from pathlib import Path
from tempfile import TemporaryDirectory

from lazycloud import App, Artifact

app = App("reports")


@app.function()
def create_report(amounts_cents: list[int]) -> str:
    with TemporaryDirectory() as directory:
        path = Path(directory) / "sales.csv"
        path.write_text(f"sales,total_cents\n{len(amounts_cents)},{sum(amounts_cents)}\n")
        artifact = Artifact.file(path)
        artifact.save()
        return artifact.public_url(expires=3600)
```

```bash theme={null}
uv run lazycloud run report:create_report '[1200, 3500, 800]'
```

Open the returned URL to download `sales.csv`. Anyone with that URL can read
the file until it expires. LazyCloud attaches the task ID for you.

`save()` uploads the file and returns a `SavedArtifact` with `artifact_id`,
`task_id`, and `filename`. If the path is a directory, `save()` zips it first.

Other ways to construct one:

```python theme={null}
Artifact.file(path, content_type=None, task_id=None)   # an existing file
Artifact.from_file(file_handle, suffix="")              # an open binary handle
Artifact.from_pil_image(image, format="png")            # a PIL image
Artifact(path=path, content_type="text/csv")            # explicit metadata
```

`artifact.zip_dir(dir_path)` zips a directory so a folder can be saved as one
artifact.

## Retrieve one

`artifact.public_url(expires=3600)` returns a URL that serves the file without
authentication until it expires, so a browser or a webhook can use it.
`artifact.exists()` and `artifact.stat()` check and describe the saved file.

Deleting the task that produced an artifact leaves the artifact in place.
Saving from outside the producing container needs an explicit `task_id=...`. The
[dashboard](/platform/dashboard#retrieve-files) lists, previews, and downloads
them.

## Retention

Artifacts expire on the same plan retention window as logs. Free keeps them
for one day, Team for 30 days, and Business for 90 days. Complimentary accounts
get the Business window.

The plan at upload time sets the window, and it counts from the upload.
`saved.expires_at` and the dashboard show the expiry date. Public URLs do not
outlive the artifact, and `artifact.delete()` removes one sooner. Artifacts bill
as volume storage. See [Plans and limits](/platform/plans).

`uv run lazycloud artifact list`, `usage`, and `delete` manage artifacts from a
terminal. See [storage commands](/cli/storage#lazycloud-artifact).
