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

# Run from Code

> Run browser automation tasks programmatically using the Python SDK, TypeScript SDK, or REST API. Poll for results, use webhooks, or wait for completion.

Run tasks programmatically using the Python SDK, TypeScript SDK, or REST API.

***

## Run a task

A task has one required parameter and one commonly used optional parameter:

* **`prompt`** (required): Natural language instructions describing what the AI should do
* **`url`** (optional): The starting page for the automation

When you call `run_task`, Skyvern spins up a cloud browser, navigates to the URL, and executes your prompt. A typical task takes 30-90 seconds depending on complexity.

<CodeGroup>
  ```python Python theme={null}
  import os
  import asyncio
  from skyvern import Skyvern

  async def main():
      client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY"))

      result = await client.run_task(
          prompt="Get the title of the top post",
          url="https://news.ycombinator.com",
      )

      print(f"Run ID: {result.run_id}")
      print(f"Status: {result.status}")

  asyncio.run(main())
  ```

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

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

    const result = await client.runTask({
      body: {
        prompt: "Get the title of the top post",
        url: "https://news.ycombinator.com",
      },
    });

    console.log(`Run ID: ${result.run_id}`);
    console.log(`Status: ${result.status}`);
  }

  main();
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.skyvern.com/v1/run/tasks" \
    -H "x-api-key: $SKYVERN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Get the title of the top post",
      "url": "https://news.ycombinator.com"
    }'
  ```
</CodeGroup>

**Example response:**

```json theme={null}
{
  "run_id": "tsk_v2_486305187432193504",
  "status": "queued",
  "output": null,
  "downloaded_files": null,
  "recording_url": null,
  "screenshot_urls": null,
  "failure_reason": null,
  "created_at": "2026-01-20T11:52:29.276851",
  "modified_at": "2026-01-20T11:52:29.484284",
  "app_url": "https://app.skyvern.com/runs/wr_486305187432193510",
  "run_type": "task_v2"
}
```

The response includes a `run_id`. Use this ID to check status, fetch results, and retrieve artifacts.

<Warning>
  `run_task` returns immediately -- the task is queued, not finished. Always poll or use webhooks to get results.
</Warning>

***

## Get results

The `run_task` call queues the task and returns immediately.

Use the `run_id` to fetch results once the task reaches a terminal state.

| Status       | Description                                                                         |
| ------------ | ----------------------------------------------------------------------------------- |
| `created`    | Task initialized, not yet queued                                                    |
| `queued`     | Waiting for an available browser                                                    |
| `running`    | AI is navigating and executing                                                      |
| `completed`  | Task finished successfully -- check `output` for results                            |
| `failed`     | Task encountered an error -- check `failure_reason` and retry or adjust your prompt |
| `terminated` | Task was manually stopped                                                           |
| `timed_out`  | Task exceeded time limit -- increase `max_steps` or simplify the task               |
| `canceled`   | Task was canceled before starting                                                   |

You have three options for retrieving results:

### Option 1: Polling

Poll `get_run` until status is terminal (`completed`, `failed`, `terminated`, `timed_out`, or `canceled`).

<CodeGroup>
  ```python Python theme={null}
  run_id = result.run_id

  while True:
      run = await client.get_run(run_id)

      if run.status in ["completed", "failed", "terminated", "timed_out", "canceled"]:
          break

      await asyncio.sleep(5)

  print(f"Output: {run.output}")
  ```

  ```typescript TypeScript theme={null}
  const runId = result.run_id;

  while (true) {
    const run = await client.getRun(runId);

    if (["completed", "failed", "terminated", "timed_out", "canceled"].includes(run.status)) {
      console.log(`Output: ${JSON.stringify(run.output)}`);
      break;
    }

    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
  ```

  ```bash cURL theme={null}
  #!/bin/bash
  RUN_ID="YOUR_RUN_ID"

  while true; do
    RESPONSE=$(curl -s -X GET "https://api.skyvern.com/v1/runs/$RUN_ID" \
      -H "x-api-key: $SKYVERN_API_KEY")

    STATUS=$(echo "$RESPONSE" | jq -r '.status')
    echo "Status: $STATUS"

    if [[ "$STATUS" == "completed" || "$STATUS" == "failed" || "$STATUS" == "terminated" || "$STATUS" == "timed_out" || "$STATUS" == "canceled" ]]; then
      echo "$RESPONSE" | jq '.output'
      break
    fi

    sleep 5
  done
  ```
</CodeGroup>

<Warning>
  Your polling loop must check **all** terminal states: `completed`, `failed`, `terminated`, `timed_out`, `canceled`. Missing one causes infinite loops.
</Warning>

### Option 2: Webhooks

Pass a `webhook_url` when creating the task. Skyvern sends a POST request to your URL when the task completes.

<CodeGroup>
  ```python Python theme={null}
  result = await client.run_task(
      prompt="Get the title of the top post",
      url="https://news.ycombinator.com",
      webhook_url="https://your-server.com/webhook",
  )
  ```

  ```typescript TypeScript theme={null}
  const result = await client.runTask({
    body: {
      prompt: "Get the title of the top post",
      url: "https://news.ycombinator.com",
      webhook_url: "https://your-server.com/webhook",
    },
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.skyvern.com/v1/run/tasks" \
    -H "x-api-key: $SKYVERN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Get the title of the top post",
      "url": "https://news.ycombinator.com",
      "webhook_url": "https://your-server.com/webhook"
    }'
  ```
</CodeGroup>

Skyvern sends a POST request with the full run data when the task completes or fails.

### Option 3: Wait for completion (Python only)

Block until the task finishes instead of polling manually.

```python Python theme={null}
result = await client.run_task(
    prompt="Get the title of the top post",
    url="https://news.ycombinator.com",
    wait_for_completion=True,
)
print(result.output)
```

***

## Understand the response

The response from polling (`get_run`) and webhooks have slightly different structures. Both contain the core task data, but webhooks include additional metadata.

<CodeGroup>
  ```json Polling Response theme={null}
  {
    "run_id": "tsk_v2_486305187432193504",
    "status": "completed",
    "output": {
      "top_post_title": "Linux kernel framework for PCIe device emulation, in userspace"
    },
    "downloaded_files": [],
    "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../recording.webm?...",
    "screenshot_urls": ["https://skyvern-artifacts.s3.amazonaws.com/.../screenshot_final.png?..."],
    "failure_reason": null,
    "errors": [],
    "step_count": 2,
    "run_type": "task_v2",
    "app_url": "https://app.skyvern.com/runs/wr_486305187432193510",
    "browser_session_id": null,
    "browser_profile_id": null,
    "created_at": "2026-01-20T11:52:29.276851",
    "modified_at": "2026-01-20T11:54:08.822807",
    "queued_at": "2026-01-20T11:52:29.483922",
    "started_at": "2026-01-20T11:52:31.835337",
    "finished_at": "2026-01-20T11:54:08.821985",
    "run_request": {
      "prompt": "Get the title of the top post",
      "url": "https://news.ycombinator.com/",
      "engine": "skyvern-2.0"
    }
  }
  ```

  ```json Webhook Payload theme={null}
  {
    "task_id": "tsk_v2_486306851394503256",
    "run_id": "tsk_v2_486306851394503256",
    "status": "completed",
    "output": {
      "top_post_title": "Linux kernel framework for PCIe device emulation, in userspace"
    },
    "summary": "I have successfully navigated to Hacker News and extracted the title of the top post.",
    "prompt": "Get the title of the top post",
    "url": "https://news.ycombinator.com/",
    "downloaded_files": [],
    "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../recording.webm?...",
    "screenshot_urls": ["https://skyvern-artifacts.s3.amazonaws.com/.../screenshot_final.png?..."],
    "failure_reason": null,
    "errors": [],
    "step_count": 2,
    "run_type": "task_v2",
    "app_url": "https://app.skyvern.com/runs/wr_486306851394503262",
    "organization_id": "o_485917350850524254",
    "workflow_run_id": "wr_486306851394503262",
    "proxy_location": "RESIDENTIAL",
    "webhook_callback_url": "https://your-server.com/webhook",
    "created_at": "2026-01-20T11:58:57.414123",
    "modified_at": "2026-01-20T12:00:31.513449",
    "queued_at": "2026-01-20T11:58:57.607233",
    "started_at": "2026-01-20T11:58:59.395028",
    "finished_at": "2026-01-20T12:00:31.512692"
  }
  ```
</CodeGroup>

**Common fields (both polling and webhook):**

| Field              | Type             | Description                                                                                       |
| ------------------ | ---------------- | ------------------------------------------------------------------------------------------------- |
| `run_id`           | string           | Unique identifier for this run                                                                    |
| `status`           | string           | Current status: `queued`, `running`, `completed`, `failed`, `terminated`, `timed_out`, `canceled` |
| `output`           | object \| null   | Extracted data from the task                                                                      |
| `downloaded_files` | array            | Files downloaded during execution                                                                 |
| `recording_url`    | string \| null   | Video recording of the browser session                                                            |
| `screenshot_urls`  | array \| null    | Screenshots captured (latest first)                                                               |
| `failure_reason`   | string \| null   | Error message if the run failed                                                                   |
| `errors`           | array            | List of errors encountered                                                                        |
| `step_count`       | integer \| null  | Number of steps executed                                                                          |
| `run_type`         | string           | Type of run: `task_v2`, `openai_cua`, `anthropic_cua`                                             |
| `app_url`          | string           | Link to view this run in Skyvern Cloud                                                            |
| `created_at`       | datetime         | When the run was created                                                                          |
| `modified_at`      | datetime         | When the run was last updated                                                                     |
| `queued_at`        | datetime \| null | When the run entered the queue                                                                    |
| `started_at`       | datetime \| null | When execution began                                                                              |
| `finished_at`      | datetime \| null | When execution completed                                                                          |

**Polling-only fields:**

| Field                    | Type            | Description                                             |
| ------------------------ | --------------- | ------------------------------------------------------- |
| `run_request`            | object          | Original request parameters (prompt, url, engine, etc.) |
| `browser_session_id`     | string \| null  | ID of the browser session used                          |
| `browser_profile_id`     | string \| null  | ID of the browser profile used                          |
| `max_screenshot_scrolls` | integer \| null | Number of scrolls for screenshots                       |
| `script_run`             | object \| null  | Script run result if AI fallback triggered              |

**Webhook-only fields:**

| Field                  | Type   | Description                                |
| ---------------------- | ------ | ------------------------------------------ |
| `task_id`              | string | Same as `run_id`                           |
| `summary`              | string | AI-generated description of what was done  |
| `prompt`               | string | The prompt from the original request       |
| `url`                  | string | The URL from the original request          |
| `organization_id`      | string | Your organization ID                       |
| `workflow_run_id`      | string | Associated workflow run ID                 |
| `proxy_location`       | string | Proxy location used (e.g., `RESIDENTIAL`)  |
| `webhook_callback_url` | string | The webhook URL that received this payload |

### Artifacts

Every run captures recordings, screenshots, and logs. See [Using Artifacts](/developers/debugging/using-artifacts) for retrieval and the full artifact type reference.

***

<Note>
  For multi-step automations that chain multiple actions, see [Browser Automation](/developers/browser-automations/overview).
</Note>
