---
title: Using Artifacts
subtitle: Access recordings, screenshots, logs, and network data for every run
description: Retrieve and inspect artifacts from Skyvern runs including browser recordings, screenshots, AI reasoning logs, DOM element trees, network HAR files, and Playwright traces to debug failures and unexpected results.
slug: debugging/using-artifacts
keywords:
  - artifact
  - recording
  - screenshot
  - HAR file
  - Playwright trace
  - DOM tree
  - AI reasoning log
  - network data
  - generated code
---

When a Skyvern run fails or produces unexpected results, artifacts are your debugging toolkit. Every run automatically captures what happened—recordings of the browser session, screenshots at each step, the AI's reasoning, and network traffic.

This page covers how to retrieve artifacts and what each type tells you.

<Tip>
Looking for a specific artifact type? Jump to the [artifact types reference](#artifact-types-reference) to see all available types, then come back here to learn how to retrieve them.
</Tip>

---

## Before you start

You need a `run_id` to retrieve artifacts. You get this when you [run a task](/running-automations/run-a-task) or workflow.

---

## Retrieve artifacts

Use `get_run_artifacts` with the `run_id` from your task or workflow run:

<CodeGroup>
```python Python
import os
from skyvern import Skyvern

client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY"))

artifacts = await client.get_run_artifacts(run_id)

for artifact in artifacts:
    print(f"{artifact.artifact_type}: {artifact.signed_url}")
```

```typescript TypeScript
import { SkyvernClient } from "@skyvern/client";

const client = new SkyvernClient({
  apiKey: process.env.SKYVERN_API_KEY,
});

const artifacts = await client.getRunArtifacts(runId);

for (const artifact of artifacts) {
  console.log(`${artifact.artifact_type}: ${artifact.signed_url}`);
}
```

```bash cURL
curl -X GET "https://api.skyvern.com/v1/runs/$RUN_ID/artifacts" \
  -H "x-api-key: $SKYVERN_API_KEY"
```
</CodeGroup>

<Note>
Signed URLs expire after 24 hours. If a URL has expired, call `get_run_artifacts` again to get fresh URLs. When running Skyvern locally, `signed_url` will be `null`—access artifacts directly from your local file system instead.
</Note>

---

## Filter by artifact type

To get only specific artifact types, pass `artifact_type`:

<CodeGroup>
```python Python
# Get only recordings and final screenshots
artifacts = await client.get_run_artifacts(
    run_id,
    artifact_type=["recording", "screenshot_final"]
)
```

```typescript TypeScript
const artifacts = await client.getRunArtifacts(runId, {
  artifact_type: ["recording", "screenshot_final"],
});
```

```bash cURL
curl -X GET "https://api.skyvern.com/v1/runs/$RUN_ID/artifacts?artifact_type=recording&artifact_type=screenshot_final" \
  -H "x-api-key: $SKYVERN_API_KEY"
```
</CodeGroup>

---

## Artifact types reference

### Visual artifacts

These show you what the browser looked like at various points.

| Type | What it contains | Use this to |
|------|------------------|-------------|
| `recording` | Full video of the browser session (WebM) | Watch the entire run, see exactly what happened |
| `screenshot` | Base screenshot capture | General page state capture |
| `screenshot_final` | Screenshot when the run ended | Check the final state—did it end on the right page? |
| `screenshot_action` | Screenshot taken after each action | See the page state after each click, type, or navigation |
| `screenshot_llm` | Screenshot sent to the LLM for decision-making | Understand what the AI "saw" when it made each decision |

**Debugging tip:** If the run failed, start with `screenshot_final` to see where it stopped, then watch the `recording` to see how it got there.

### AI reasoning artifacts

These show you why the AI made each decision.

| Type | What it contains | Use this to |
|------|------------------|-------------|
| `llm_prompt` | The prompt sent to the LLM | See exactly what instructions the AI received |
| `llm_request` | Full request including context | Check if the right context was included |
| `llm_response` | Raw LLM response | See the AI's unprocessed output |
| `llm_response_parsed` | Parsed response (extracted actions) | Understand what actions the AI decided to take |
| `llm_response_rendered` | Parsed response with real URLs | Debug URL targeting issues (see below) |

**Debugging tip:** If the AI did something unexpected, check `llm_prompt` to see if your prompt was interpreted correctly, then `llm_response_parsed` to see what action it extracted.

**About `llm_response_rendered`:** Skyvern hashes URLs before sending them to the LLM to reduce token usage and avoid confusing the model with long query strings. The `llm_response_parsed` artifact contains these hashed placeholders (like `{{_a1b2c3}}`), while `llm_response_rendered` shows the same response with actual URLs substituted back in. Use this when you need to verify which exact URL the AI targeted.

### Page structure artifacts

These show how Skyvern interpreted the page.

| Type | What it contains | Use this to |
|------|------------------|-------------|
| `visible_elements_tree` | DOM tree of visible elements (JSON) | See which elements Skyvern detected |
| `visible_elements_tree_trimmed` | Trimmed tree (sent to LLM) | See what the AI could "see" |
| `visible_elements_tree_in_prompt` | Element tree as plain text | Read exactly what was embedded in the prompt |
| `visible_elements_id_css_map` | CSS selectors for each element | Debug element targeting issues |
| `visible_elements_id_frame_map` | Element-to-iframe mapping | Debug elements inside iframes |
| `visible_elements_id_xpath_map` | XPath selectors for each element | Alternative element targeting debug |
| `hashed_href_map` | Mapping of hashed URLs to original URLs | Decode URL placeholders in LLM responses |
| `html` | Generic HTML capture | Inspect page HTML |
| `html_scrape` | Full HTML captured during scraping | Inspect the raw page structure |
| `html_action` | HTML captured after an action | See how the page changed after each action |

**Debugging tip:** If the AI couldn't find an element, check `visible_elements_tree` to see if it was detected. If not, the element might be in an iframe, dynamically loaded, or outside the viewport.

**About the element tree variants:** The `visible_elements_tree` is a JSON structure, while `visible_elements_tree_in_prompt` is the plain-text representation that gets embedded directly into the LLM prompt. The latter is often easier to read when debugging prompt issues. If you're debugging iframe-related problems, `visible_elements_id_frame_map` shows which frame contains each element ID.

### Log artifacts

These contain structured execution data.

| Type | What it contains | Use this to |
|------|------------------|-------------|
| `skyvern_log` | Formatted execution logs | Read through the run step-by-step |
| `skyvern_log_raw` | Raw JSON logs | Parse programmatically for automation |
| `browser_console_log` | Browser console output | Debug JavaScript errors on the page |

**Debugging tip:** `skyvern_log` is human-readable and shows the flow of execution. Start here for an overview before diving into specific artifacts.

### Network artifacts

| Type | What it contains | Use this to |
|------|------------------|-------------|
| `har` | HTTP Archive (network requests/responses) | Debug API calls, check for failed requests, see response data |
| `trace` | Playwright trace file | Replay the session in Playwright Trace Viewer |

**Debugging tip:** The HAR file captures every network request. If a form submission failed, check the HAR to see if the request was sent and what the server responded.

### File artifacts

| Type | What it contains | Use this to |
|------|------------------|-------------|
| `script_file` | Generated Playwright scripts | See the code Skyvern would use to repeat this task |

---

## Artifact response fields

| Field | Type | Description |
|-------|------|-------------|
| `artifact_id` | string | Unique identifier |
| `artifact_type` | string | Type (see tables above) |
| `uri` | string | Internal storage path |
| `signed_url` | string \| null | Pre-signed URL for downloading |
| `task_id` | string \| null | Associated task ID |
| `step_id` | string \| null | Associated step ID |
| `run_id` | string \| null | Run ID (e.g., `tsk_v2_...`, `wr_...`) |
| `workflow_run_id` | string \| null | Workflow run ID |
| `workflow_run_block_id` | string \| null | Workflow block ID |
| `organization_id` | string | Your organization |
| `created_at` | datetime | When created |
| `modified_at` | datetime | When modified |

---

## Next steps

<CardGroup cols={2}>
  <Card
    title="Troubleshooting Guide"
    icon="wrench"
    href="/debugging/troubleshooting-guide"
  >
    Common issues and how to fix them
  </Card>
  <Card
    title="Error Handling"
    icon="triangle-exclamation"
    href="/going-to-production/error-handling"
  >
    Map errors to custom codes for programmatic handling
  </Card>
</CardGroup>
