Skip to main content

Install and initialize

# Requires Python 3.11+
pip install skyvern
import asyncio
from skyvern import Skyvern

async def main():
    client = Skyvern(api_key="YOUR_API_KEY")
    result = await client.run_task(
        prompt="Get the title of the top post on Hacker News",
        url="https://news.ycombinator.com",
        wait_for_completion=True,
    )
    print(result.output)

asyncio.run(main())
Constructor:
Skyvern(
    api_key: str,                          # Required
    base_url: str | None = None,           # Override for self-hosted deployments
    environment: SkyvernEnvironment = CLOUD,# CLOUD, STAGING, or LOCAL
    timeout: float | None = None,          # HTTP request timeout (seconds)
)

# Local mode (Python only - runs entirely on your machine, reads .env)
client = Skyvern.local()

Browser Automation

SkyvernBrowser

# Launch / connect
browser = await client.launch_cloud_browser(timeout=60, proxy_location=None)
browser = await client.use_cloud_browser(timeout=60, proxy_location=None)
browser = await client.connect_to_cloud_browser_session("pbs_abc123")
browser = await client.connect_to_browser_over_cdp("http://localhost:9222")
browser = await client.launch_local_browser(headless=False, port=9222)  # Python only

# Get pages
page = await browser.get_working_page()   # Most recent page, or creates one
page = await browser.new_page()            # Always creates a new tab
page = await browser.get_page_for(pw_page) # Wrap existing Playwright Page (Python only)
await browser.close()                      # Close browser and cloud session

SkyvernPage

AI-enhanced Playwright methods - pass a selector for standard Playwright, add a prompt for AI fallback, or use prompt alone for pure AI.
# act - freeform AI action
await page.act("Click the login button")

# extract - structured data extraction
data = await page.extract("Extract all products", schema={...})

# validate - page state assertion, returns bool
ok = await page.validate("User is logged in")

# prompt - ask LLM about the page
result = await page.prompt("What is the heading?", schema={...})

# locator - AI element locator returning chainable AILocator (Python only)
locator = page.locator(prompt="the submit button")
await locator.click()

# click - selector, AI, or both with fallback
await page.click("#submit-btn")
await page.click(prompt="Click the submit button")
await page.click("#submit-btn", prompt="Click submit")

# fill - selector, AI, or both with fallback
await page.fill("#email", value="user@example.com")
await page.fill(prompt="Fill email with user@example.com")

# select_option - selector, AI, or both with fallback
await page.select_option("#country", value="us")
await page.select_option(prompt="Select United States")

# type - character-by-character input (Python only)
await page.type("#search", value="query")

# hover (Python only)
await page.hover("#menu-item", intention="Hover over the menu")

# scroll (Python only)
await page.scroll(0, 500)

# upload_file (Python only)
await page.upload_file("#file-input", files="/path/to/file.pdf")

# fill_form - AI full form fill (Python only)
await page.fill_form(data={"name": "John", "email": "john@example.com"})

# fill_multipage_form - across page transitions (Python only)
await page.fill_multipage_form(data={...}, max_pages=5)

# fill_from_mapping - explicit field→value mapping (Python only)
await page.fill_from_mapping(form_fields=fields, mapping={0: "John"}, data={...})

# extract_form_fields - get all fields with metadata (Python only)
fields = await page.extract_form_fields()

# validate_mapping - verify mapping works (Python only)
is_valid = await page.validate_mapping(form_fields=fields, mapping={...}, prompt="Validate fields")

# fill_autocomplete - typeahead handling (Python only)
await page.fill_autocomplete(selector="#city", value="San Francisco")

# frame_switch - switch iframe context (Python only)
await page.frame_switch(selector="#payment-iframe")
page.frame_main()                    # back to main frame
frames = await page.frame_list()     # list all frames

Page Agent

Full task/workflow execution in the context of the current page. Always waits for completion.
# run_task
result = await page.agent.run_task("Fill out the form", data_extraction_schema={...}, max_steps=10, timeout=1800)

# login - supports skyvern, bitwarden, onepassword, azure_vault
await page.agent.login(credential_type=CredentialType.skyvern, credential_id="cred_123")

# download_files
result = await page.agent.download_files("Download the invoice PDF", download_suffix=".pdf")

# run_workflow
result = await page.agent.run_workflow("wpid_abc123", parameters={"key": "value"})

Tasks

run_task

result = await client.run_task(
    prompt: str,                                # Required
    url: str | None = None,
    engine: RunEngine = RunEngine.skyvern_v2,
    wait_for_completion: bool = False,
    timeout: float = 1800,
    max_steps: int | None = None,
    data_extraction_schema: dict | str | None = None,
    browser_session_id: str | None = None,
    publish_workflow: bool = False,
    proxy_location: ProxyLocation | None = None,
    webhook_url: str | None = None,
    error_code_mapping: dict[str, str] | None = None,
    totp_identifier: str | None = None,
    totp_url: str | None = None,
    title: str | None = None,
    model: dict | None = None,
    user_agent: str | None = None,
    extra_http_headers: dict[str, str] | None = None,
    include_action_history_in_verification: bool | None = None,
    max_screenshot_scrolls: int | None = None,
    browser_address: str | None = None,
    run_with: str | None = None,
) -> TaskRunResponse
TaskRunResponse: run_id, status, output, failure_reason, downloaded_files, recording_url, screenshot_urls, app_url, step_count, script_run, created_at, finished_at

get_run

get_run(run_id) → GetRunResponse

cancel_run

cancel_run(run_id)

get_run_timeline

get_run_timeline(run_id) → list[WorkflowRunTimeline]

get_run_artifacts

get_run_artifacts(run_id, artifact_type?) → list[Artifact]

get_artifact

get_artifact(artifact_id) → Artifact

get_runs_v2

get_runs_v2(page?, page_size?, status?, search_key?) → list[TaskRunListItem]

retry_run_webhook

retry_run_webhook(run_id, webhook_url?)

Workflows

run_workflow

result = await client.run_workflow(
    workflow_id: str,                       # Required. Permanent ID (wpid_...).
    parameters: dict | None = None,
    wait_for_completion: bool = False,
    timeout: float = 1800,
    run_with: str | None = None,            # "code" or "agent"
    ai_fallback: bool | None = None,
    browser_session_id: str | None = None,
    browser_profile_id: str | None = None,
    proxy_location: ProxyLocation | None = None,
    max_steps_override: int | None = None,
    webhook_url: str | None = None,
    title: str | None = None,
    template: bool | None = None,
    totp_identifier: str | None = None,
    totp_url: str | None = None,
    user_agent: str | None = None,
    extra_http_headers: dict[str, str] | None = None,
    max_screenshot_scrolls: int | None = None,
    browser_address: str | None = None,
) -> WorkflowRunResponse
WorkflowRunResponse: Same as TaskRunResponse plus run_with, ai_fallback, script_run.

create_workflow

create_workflow(json_definition?, yaml_definition?, folder_id?) → Workflow

get_workflow

get_workflow(workflow_permanent_id, version?, template?) → Workflow

get_workflows

get_workflows(page?, page_size?, only_saved_tasks?, only_workflows?, only_templates?, title?, search_key?, folder_id?, status?, template?) → list[Workflow]

get_workflow_versions

get_workflow_versions(workflow_permanent_id, template?) → list[Workflow]

update_workflow

update_workflow(workflow_id, json_definition?, yaml_definition?) → Workflow

delete_workflow

delete_workflow(workflow_id)

get_workflow_runs

get_workflow_runs(page?, page_size?, status?, search_key?, error_code?) → list[WorkflowRun]

update_workflow_folder

update_workflow_folder(workflow_permanent_id, folder_id?) → Workflow
Workflow fields: workflow_id, workflow_permanent_id, version, title, workflow_definition, status, created_at

Browser Sessions

create_browser_session

create_browser_session(timeout?, proxy_location?, extensions?, browser_type?, browser_profile_id?) → BrowserSessionResponse

get_browser_session

get_browser_session(browser_session_id) → BrowserSessionResponse

get_browser_sessions

get_browser_sessions() → list[BrowserSessionResponse]

close_browser_session

close_browser_session(browser_session_id)
BrowserSessionResponse fields: browser_session_id, status, browser_address, app_url, timeout, started_at, created_at

Browser Profiles

create_browser_profile

create_browser_profile(name, description?, workflow_run_id?, browser_session_id?) → BrowserProfile

list_browser_profiles

list_browser_profiles(include_deleted?) → list[BrowserProfile]

get_browser_profile

get_browser_profile(profile_id) → BrowserProfile

delete_browser_profile

delete_browser_profile(profile_id)
BrowserProfile fields: browser_profile_id, name, description, created_at

Credentials

create_credential

create_credential(name, credential_type, credential, vault_type?) → CredentialResponse

get_credential

get_credential(credential_id) → CredentialResponse

get_credentials

get_credentials(page?, page_size?, vault_type?) → list[CredentialResponse]

update_credential

update_credential(credential_id, name, credential_type, credential, vault_type?) → CredentialResponse

delete_credential

delete_credential(credential_id)

send_totp_code

send_totp_code(totp_identifier, content, task_id?, workflow_id?, workflow_run_id?, source?, expired_at?, type?) → TotpCode

Helpers

login

login(credential_type, url?, credential_id?, prompt?, browser_session_id?, browser_profile_id?, browser_address?, proxy_location?, webhook_url?, totp_identifier?, totp_url?, extra_http_headers?, max_screenshot_scrolling_times?, wait_for_completion?, timeout?) → WorkflowRunResponse
Credential-specific parameters: bitwarden_collection_id, bitwarden_item_id, onepassword_vault_id, onepassword_item_id, azure_vault_name, azure_vault_username_key, azure_vault_password_key, azure_vault_totp_secret_key.

download_files

download_files(navigation_goal, url?, browser_session_id?, browser_profile_id?, proxy_location?, webhook_url?, download_suffix?, download_timeout?, max_steps_per_run?, extra_http_headers?, totp_identifier?, totp_url?, browser_address?, max_screenshot_scrolling_times?) → WorkflowRunResponse
Python does not support wait_for_completion - poll with get_run(). TypeScript supports waitForCompletion.

upload_file

upload_file(file) → UploadFileResponse
Returns s3uri and presigned_url.

Error Handling

from skyvern.client.core import ApiError
from skyvern.client.errors import NotFoundError

try:
    run = await client.get_run("tsk_nonexistent")
except NotFoundError as e:
    print(e.status_code, e.body)    # 404
except ApiError as e:
    print(e.status_code, e.body)    # Any other HTTP error
Error types: BadRequestError (400), ForbiddenError (403), NotFoundError (404), ConflictError (409), UnprocessableEntityError (422). All inherit from ApiError (Python) or SkyvernError (TypeScript). Run failure is not an exception - check result.status (completed, failed, terminated, timed_out, canceled).

Request options

Every method accepts request_options (Python) or a second options argument (TypeScript) for per-request overrides:
from skyvern.client.core import RequestOptions

request_options=RequestOptions(
    timeout_in_seconds=120,
    max_retries=3,
    additional_headers={"x-custom-header": "value"},
)

Key constraints

  • browser_profile_id works with run_workflow only - silently ignored by run_task.
  • Python download_files does not support wait_for_completion - poll manually or use webhooks.
  • Only workflow runs with persist_browser_session=True produce archives for profile creation.
  • launch_local_browser requires Python local mode (Skyvern.local()).
  • page.agent methods always wait for completion.
  • Python-only features: launch_local_browser, get_page_for, locator/AILocator, type, hover, scroll, upload_file (page-level), form automation (fill_form, fill_multipage_form, fill_from_mapping, extract_form_fields, validate_mapping, fill_autocomplete), iframe management (frame_switch, frame_main, frame_list).