394 lines
11 KiB
Plaintext
394 lines
11 KiB
Plaintext
---
|
|
title: API Quickstart
|
|
slug: getting-started/quickstart
|
|
---
|
|
|
|
Run your first browser automation in 5 minutes. By the end of this guide, you'll scrape the top post from Hacker News using Skyvern's AI agent.
|
|
|
|
<Note>
|
|
Prefer a visual interface? Try the [Cloud UI](/cloud/getting-started) instead — no code required.
|
|
</Note>
|
|
|
|
## Step 1: Get your API key
|
|
|
|
<img src="/images/get-api-key.png" alt="Get Skyvern API key" />
|
|
|
|
Sign up at [app.skyvern.com](https://app.skyvern.com) and go to [Settings](https://app.skyvern.com/settings) to copy your API key.
|
|
|
|
When you make API calls, Skyvern spins up a cloud browser, executes your task with AI, and returns the results. You can watch the browser live at any time.
|
|
|
|
## Step 2: Install the SDK
|
|
|
|
<CodeGroup>
|
|
```bash Python
|
|
pip install skyvern
|
|
```
|
|
|
|
```bash TypeScript
|
|
npm install @skyvern/client
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Accordion title="Troubleshooting: Python version errors">
|
|
The Skyvern SDK requires Python 3.11, 3.12, or 3.13. If you encounter version errors, try using pipx:
|
|
|
|
```bash
|
|
pipx install skyvern
|
|
```
|
|
|
|
pipx installs Python packages in isolated environments while making them globally available.
|
|
</Accordion>
|
|
|
|
## Step 3: Run your first task
|
|
|
|
Let's scrape the title of the #1 post on Hacker News. You only need two parameters:
|
|
|
|
- **`prompt`** — Natural language instructions for what the AI should do. Be specific about the data you want extracted.
|
|
- **`url`** — The starting page. Skyvern's AI will navigate from here based on your prompt.
|
|
|
|
The SDK uses async/await because Skyvern spins up a cloud browser and executes your task remotely, which can take 30-60 seconds.
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
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="Go to news.ycombinator.com and get the title of the #1 post",
|
|
url="https://news.ycombinator.com",
|
|
)
|
|
|
|
print(f"Run ID: {result.run_id}")
|
|
print(f"Status: {result.status}")
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
```typescript TypeScript
|
|
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: "Go to news.ycombinator.com and get the title of the #1 post",
|
|
url: "https://news.ycombinator.com",
|
|
},
|
|
});
|
|
|
|
console.log(`Run ID: ${result.run_id}`);
|
|
console.log(`Status: ${result.status}`);
|
|
}
|
|
|
|
main();
|
|
```
|
|
|
|
```bash cURL
|
|
curl -X POST "https://api.skyvern.com/v1/run/tasks" \
|
|
-H "x-api-key: $SKYVERN_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"prompt": "Go to news.ycombinator.com and get the title of the #1 post",
|
|
"url": "https://news.ycombinator.com"
|
|
}'
|
|
```
|
|
</CodeGroup>
|
|
|
|
The response includes a `run_id` you'll use to check status and fetch results.
|
|
|
|
## Step 4: Check the status
|
|
|
|
Since tasks run asynchronously, you have two options:
|
|
|
|
1. **Polling** — Periodically check the task status (shown below)
|
|
2. **Webhooks** — Get notified when the task completes ([see webhooks guide](/running-tasks/webhooks-faq))
|
|
|
|
The code below polls every 5 seconds until the task reaches a terminal state. Once complete, `run.output` contains the extracted data as a dictionary.
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
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="Go to news.ycombinator.com and get the title of the #1 post",
|
|
url="https://news.ycombinator.com",
|
|
)
|
|
|
|
run_id = result.run_id
|
|
print(f"Task started: {run_id}")
|
|
|
|
while True:
|
|
run = await client.get_run(run_id)
|
|
print(f"Status: {run.status}")
|
|
|
|
if run.status in ["completed", "failed", "terminated", "timed_out", "canceled"]:
|
|
break
|
|
|
|
await asyncio.sleep(5)
|
|
|
|
print(f"Final status: {run.status}")
|
|
print(f"Output: {run.output}")
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
```typescript TypeScript
|
|
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: "Go to news.ycombinator.com and get the title of the #1 post",
|
|
url: "https://news.ycombinator.com",
|
|
},
|
|
});
|
|
|
|
const runId = result.run_id;
|
|
console.log(`Task started: ${runId}`);
|
|
|
|
while (true) {
|
|
const run = await client.getRun(runId);
|
|
console.log(`Status: ${run.status}`);
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
main();
|
|
```
|
|
|
|
```bash cURL
|
|
RUN_ID="your_run_id_here"
|
|
|
|
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>
|
|
|
|
**Run states:**
|
|
- `created` — Task initialized, not yet queued
|
|
- `queued` — Waiting for an available browser
|
|
- `running` — AI is navigating and executing
|
|
- `completed` — Task finished successfully
|
|
- `failed` — Task encountered an error
|
|
- `terminated` — Task was manually stopped
|
|
- `timed_out` — Task exceeded time limit
|
|
- `canceled` — Task was cancelled before starting
|
|
|
|
## Step 5: View your results
|
|
|
|
When the task completes, you'll get a response like this:
|
|
|
|
```json
|
|
{
|
|
"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/v1/production/.../screenshot_final.png?..."],
|
|
"app_url": "https://app.skyvern.com/runs/wr_486305187432193510",
|
|
"step_count": 2,
|
|
"run_type": "task_v2"
|
|
}
|
|
```
|
|
|
|
The `output` contains whatever data the AI extracted based on your prompt. The `app_url` links to the Cloud UI where you can view the full run details.
|
|
|
|
## Step 6: Watch the recording
|
|
|
|
Every task is recorded. There are two ways to access recordings:
|
|
|
|
### From the API response
|
|
|
|
The `recording_url` field is included in every completed run response:
|
|
|
|
```json
|
|
{
|
|
"run_id": "tsk_v2_486305187432193504",
|
|
"status": "completed",
|
|
"recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/o_485917350850524254/tsk_.../recording.webm?AWSAccessKeyId=...&Signature=...&Expires=..."
|
|
}
|
|
```
|
|
|
|
### From the Cloud UI
|
|
|
|
Navigate to [Runs](https://app.skyvern.com/runs) and click on your run to see the Recording tab.
|
|
|
|
<img src="/images/view-recording.png" alt="Recording tab in Skyvern Cloud" />
|
|
|
|
### What you'll see
|
|
|
|
- **Live browser view** — Watch the AI navigate in real-time
|
|
- **Recording** — Full video replay of the session
|
|
- **Actions** — Step-by-step breakdown with screenshots
|
|
- **AI Reasoning** — See why the AI made each decision
|
|
|
|
This is invaluable for debugging and understanding how Skyvern interprets your prompts.
|
|
|
|
---
|
|
|
|
## Run with a local browser
|
|
|
|
You can run Skyvern with a browser on your own machine. This is useful for development, debugging, or automating internal tools on your local network.
|
|
|
|
**Prerequisites:**
|
|
- Skyvern SDK installed (`pip install skyvern`)
|
|
- PostgreSQL database (local install or Docker)
|
|
- An LLM API key (OpenAI, Anthropic, Azure OpenAI, Gemini, Ollama, or any OpenAI-compatible provider)
|
|
|
|
<Note>
|
|
Docker is optional. If you have PostgreSQL installed locally, Skyvern will detect and use it automatically. Use `skyvern init --no-postgres` to skip database setup entirely if you're managing PostgreSQL separately.
|
|
</Note>
|
|
|
|
### Set up local Skyvern
|
|
|
|
```bash
|
|
skyvern init
|
|
```
|
|
|
|
<p align="center">
|
|
<img src="/images/skyvern-init.gif" alt="Skyvern init interactive setup wizard" />
|
|
</p>
|
|
|
|
|
|
This interactive wizard will:
|
|
1. Set up your database (detects local PostgreSQL or uses Docker)
|
|
2. Configure your LLM provider
|
|
3. Choose browser mode (headless, headful, or connect to existing Chrome)
|
|
4. Generate local API credentials
|
|
5. Download the Chromium browser
|
|
|
|
This will generate a .env file that stores your local configuration, LLM api keys and your local `BASE_URL` and `SKYVERN_API_KEY`:
|
|
```.env
|
|
ENV='local'
|
|
ENABLE_OPENAI='true'
|
|
OPENAI_API_KEY='<API_KEY>'
|
|
...
|
|
LLM_KEY='OPENAI_GPT4O'
|
|
SECONDARY_LLM_KEY=''
|
|
BROWSER_TYPE='chromium-headful'
|
|
MAX_SCRAPING_RETRIES='0'
|
|
VIDEO_PATH='./videos'
|
|
BROWSER_ACTION_TIMEOUT_MS='5000'
|
|
MAX_STEPS_PER_RUN='50'
|
|
LOG_LEVEL='INFO'
|
|
LITELLM_LOG='CRITICAL'
|
|
DATABASE_STRING='postgresql+psycopg://skyvern@localhost/skyvern'
|
|
PORT='8000'
|
|
...
|
|
SKYVERN_BASE_URL='http://localhost:8000'
|
|
SKYVERN_API_KEY='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ5MTMzODQ2MDksInN1YiI6Im9fNDg0MjIwNjY3MzYzNzA2Njk4In0.Crwy0-y7hpMVSyhzNJGzDu_oaMvrK76RbRb7YhSo3YA'
|
|
```
|
|
|
|
### Start the local server
|
|
|
|
```bash
|
|
skyvern run server
|
|
```
|
|
|
|
<p align="center">
|
|
<img src="/images/skyvern-run-server.gif" alt="Skyvern local server logs" />
|
|
</p>
|
|
|
|
### Run a task locally
|
|
|
|
The only difference from cloud is the `base_url` parameter pointing to your local server. The API is identical, so the same code works in both environments — develop locally, deploy to cloud without changes.
|
|
|
|
```python
|
|
import os
|
|
import asyncio
|
|
from skyvern import Skyvern
|
|
|
|
async def main():
|
|
client = Skyvern(
|
|
base_url="http://localhost:8000",
|
|
api_key=os.getenv("SKYVERN_API_KEY")
|
|
)
|
|
|
|
result = await client.run_task(
|
|
prompt="Go to news.ycombinator.com and get the title of the #1 post",
|
|
url="https://news.ycombinator.com",
|
|
)
|
|
|
|
print(f"Run ID: {result.run_id}")
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
A browser window will open on your machine (if you chose headful mode). Recordings and logs are saved in the directory where you started the server.
|
|
|
|
<video style={{ aspectRatio: '16 / 9', width: '100%' }} controls>
|
|
<source src="https://github.com/naman06dev/skyvern-docs/raw/8706c85d746e2a6870d81b6a95eaa511ad66dbf8/fern/images/skyvern-agent-local.mp4" type="video/mp4" />
|
|
</video>
|
|
|
|
---
|
|
|
|
## Next steps
|
|
|
|
<CardGroup cols={2}>
|
|
<Card
|
|
title="Extract Structured Data"
|
|
icon="database"
|
|
href="/running-tasks/run-tasks"
|
|
>
|
|
Define a schema to get typed JSON output from your automations
|
|
</Card>
|
|
<Card
|
|
title="Handle Logins"
|
|
icon="key"
|
|
href="/credentials/introduction"
|
|
>
|
|
Store credentials securely for sites that require authentication
|
|
</Card>
|
|
<Card
|
|
title="Build Workflows"
|
|
icon="diagram-project"
|
|
href="/workflows/manage-workflows"
|
|
>
|
|
Chain multiple steps together for complex automations
|
|
</Card>
|
|
<Card
|
|
title="Use Webhooks"
|
|
icon="webhook"
|
|
href="/running-tasks/webhooks-faq"
|
|
>
|
|
Get notified when tasks complete instead of polling
|
|
</Card>
|
|
</CardGroup>
|