Skip to main content

Overview

Skyvern supports proxy and geolocation configuration to help you:
  • Access geo-restricted content
  • Test from different locations
  • Comply with regional requirements
  • Avoid rate limiting and blocking
  • Simulate users from specific regions

Proxy Locations

Skyvern provides residential proxies in multiple countries and regions:

Available Proxy Locations

from skyvern.schemas.runs import ProxyLocation

class ProxyLocation(StrEnum):
    # United States
    RESIDENTIAL = "RESIDENTIAL"           # US (general)
    US_CA = "US-CA"                      # California
    US_NY = "US-NY"                      # New York
    US_TX = "US-TX"                      # Texas
    US_FL = "US-FL"                      # Florida
    US_WA = "US-WA"                      # Washington
    
    # Europe
    RESIDENTIAL_GB = "RESIDENTIAL_GB"    # United Kingdom
    RESIDENTIAL_DE = "RESIDENTIAL_DE"    # Germany
    RESIDENTIAL_FR = "RESIDENTIAL_FR"    # France
    RESIDENTIAL_ES = "RESIDENTIAL_ES"    # Spain
    RESIDENTIAL_IE = "RESIDENTIAL_IE"    # Ireland
    RESIDENTIAL_IT = "RESIDENTIAL_IT"    # Italy
    RESIDENTIAL_NL = "RESIDENTIAL_NL"    # Netherlands
    
    # Asia Pacific
    RESIDENTIAL_JP = "RESIDENTIAL_JP"    # Japan
    RESIDENTIAL_IN = "RESIDENTIAL_IN"    # India
    RESIDENTIAL_AU = "RESIDENTIAL_AU"    # Australia
    RESIDENTIAL_NZ = "RESIDENTIAL_NZ"    # New Zealand
    RESIDENTIAL_KR = "RESIDENTIAL_KR"    # South Korea
    RESIDENTIAL_PH = "RESIDENTIAL_PH"    # Philippines
    
    # Americas (Other)
    RESIDENTIAL_CA = "RESIDENTIAL_CA"    # Canada
    RESIDENTIAL_MX = "RESIDENTIAL_MX"    # Mexico
    RESIDENTIAL_BR = "RESIDENTIAL_BR"    # Brazil
    RESIDENTIAL_AR = "RESIDENTIAL_AR"    # Argentina
    
    # Other
    RESIDENTIAL_TR = "RESIDENTIAL_TR"    # Turkey
    RESIDENTIAL_ZA = "RESIDENTIAL_ZA"    # South Africa
    RESIDENTIAL_ISP = "RESIDENTIAL_ISP"  # ISP proxies
    
    NONE = "NONE"                        # No proxy

Using Proxy Locations

In Task Runs

from skyvern import Skyvern
from skyvern.schemas.runs import ProxyLocation

skyvern = Skyvern(api_key="your-api-key")

# Run task from UK
task = await skyvern.run_task(
    prompt="Check product availability",
    url="https://shop.example.co.uk",
    proxy_location=ProxyLocation.RESIDENTIAL_GB
)

# Run task from Japan
task = await skyvern.run_task(
    prompt="Extract pricing information",
    url="https://example.jp",
    proxy_location=ProxyLocation.RESIDENTIAL_JP
)

In Workflow Runs

workflow_run = await skyvern.run_workflow(
    workflow_id="wpid_price_comparison",
    parameters={"product_id": "ABC123"},
    proxy_location=ProxyLocation.RESIDENTIAL_DE  # Germany proxy
)

Via API

curl -X POST https://api.skyvern.com/api/v1/tasks \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Extract product information",
    "url": "https://example.com",
    "proxy_location": "RESIDENTIAL_FR"
  }'

Granular Geolocation Targeting

For more precise targeting, use the GeoTarget object:

GeoTarget Structure

from skyvern.schemas.runs import GeoTarget

class GeoTarget(BaseModel):
    country: str              # ISO 3166-1 alpha-2 (e.g., "US", "GB")
    subdivision: str | None   # ISO 3166-2 (e.g., "CA" for California)
    city: str | None          # GeoNames English name

City-Level Targeting

# Target New York City specifically
task = await skyvern.run_task(
    prompt="Check local store availability",
    url="https://example.com/stores",
    proxy_location=GeoTarget(
        country="US",
        subdivision="NY",
        city="New York"
    )
)

# Target London, UK
task = await skyvern.run_task(
    prompt="Check UK-specific content",
    url="https://example.co.uk",
    proxy_location=GeoTarget(
        country="GB",
        city="London"
    )
)

# Target California (state-level)
task = await skyvern.run_task(
    prompt="Test California-specific features",
    url="https://example.com",
    proxy_location=GeoTarget(
        country="US",
        subdivision="CA"
    )
)

Using Dict Format

# You can also use dict format
task = await skyvern.run_task(
    prompt="Check regional pricing",
    url="https://example.com",
    proxy_location={
        "country": "US",
        "subdivision": "CA",
        "city": "San Francisco"
    }
)

Via API

curl -X POST https://api.skyvern.com/api/v1/tasks \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Extract product information",
    "url": "https://example.com",
    "proxy_location": {
      "country": "US",
      "subdivision": "CA",
      "city": "Los Angeles"
    }
  }'

Supported Countries

SUPPORTED_GEO_COUNTRIES = {
    "US",  # United States
    "AR",  # Argentina
    "AU",  # Australia
    "BR",  # Brazil
    "CA",  # Canada
    "DE",  # Germany
    "ES",  # Spain
    "FR",  # France
    "GB",  # United Kingdom
    "IE",  # Ireland
    "IN",  # India
    "IT",  # Italy
    "JP",  # Japan
    "MX",  # Mexico
    "NL",  # Netherlands
    "NZ",  # New Zealand
    "PH",  # Philippines
    "KR",  # South Korea
    "TR",  # Turkey
    "ZA",  # South Africa
}

Timezone Configuration

Proxies automatically set the browser timezone to match the proxy location:
from skyvern.schemas.runs import get_tzinfo_from_proxy

# Timezone is automatically configured based on proxy
task = await skyvern.run_task(
    prompt="Check time-sensitive content",
    url="https://example.com",
    proxy_location=ProxyLocation.RESIDENTIAL_JP  # Uses Asia/Tokyo timezone
)

Timezone Mappings

# Examples of automatic timezone mapping:
ProxyLocation.US_CA"America/Los_Angeles"
ProxyLocation.US_NY"America/New_York"
ProxyLocation.RESIDENTIAL_GB"Europe/London"
ProxyLocation.RESIDENTIAL_JP"Asia/Tokyo"
ProxyLocation.RESIDENTIAL_AU"Australia/Sydney"
ProxyLocation.RESIDENTIAL_IN"Asia/Kolkata"

Use Cases

1. Multi-Region Testing

# Test product availability in different regions
regions = [
    ("US", ProxyLocation.RESIDENTIAL),
    ("UK", ProxyLocation.RESIDENTIAL_GB),
    ("Japan", ProxyLocation.RESIDENTIAL_JP),
    ("Australia", ProxyLocation.RESIDENTIAL_AU),
]

results = {}
for region_name, proxy in regions:
    task = await skyvern.run_task(
        prompt="Check product availability and pricing",
        url="https://shop.example.com/product/ABC123",
        proxy_location=proxy,
        data_extraction_schema={
            "available": "boolean",
            "price": "number",
            "currency": "string"
        }
    )
    results[region_name] = task.output

print("Regional availability:")
for region, data in results.items():
    print(f"{region}: ${data['price']} {data['currency']} - {'Available' if data['available'] else 'Out of stock'}")

2. Geo-Restricted Content

# Access content only available in specific regions
task = await skyvern.run_task(
    prompt="Extract UK-specific offers",
    url="https://example.co.uk/offers",
    proxy_location=ProxyLocation.RESIDENTIAL_GB
)

print(f"UK Offers: {task.output}")

3. Rate Limiting Avoidance

import asyncio
from itertools import cycle

# Rotate through different proxies
proxies = cycle([
    ProxyLocation.US_CA,
    ProxyLocation.US_NY,
    ProxyLocation.US_TX,
    ProxyLocation.US_FL,
])

for i in range(100):
    task = await skyvern.run_task(
        prompt=f"Scrape page {i}",
        url=f"https://example.com/page/{i}",
        proxy_location=next(proxies)  # Rotate proxies
    )
    await asyncio.sleep(1)  # Rate limiting

4. Compliance Testing

# Test GDPR compliance from EU locations
eu_locations = [
    ProxyLocation.RESIDENTIAL_DE,
    ProxyLocation.RESIDENTIAL_FR,
    ProxyLocation.RESIDENTIAL_IT,
    ProxyLocation.RESIDENTIAL_ES,
]

for location in eu_locations:
    task = await skyvern.run_task(
        prompt="Check cookie consent and data privacy notices",
        url="https://example.com",
        proxy_location=location,
        data_extraction_schema={
            "cookie_consent_shown": "boolean",
            "gdpr_compliant": "boolean",
            "privacy_policy_link": "string"
        }
    )
    print(f"{location}: GDPR compliant = {task.output['gdpr_compliant']}")

5. State-Specific Content

# Check state-specific regulations or content
task = await skyvern.run_task(
    prompt="Extract California-specific privacy information",
    url="https://example.com/privacy",
    proxy_location=GeoTarget(
        country="US",
        subdivision="CA"
    )
)

Browser Sessions with Proxy

Persistent Proxy Configuration

# Browser sessions maintain proxy configuration
workflow_run = await skyvern.run_workflow(
    workflow_id="wpid_123",
    proxy_location=ProxyLocation.RESIDENTIAL_GB,
    browser_session_id="pbs_existing"  # Will use GB proxy
)

# Session metadata includes proxy info
session = await skyvern.get_browser_session("pbs_123")
print(f"Proxy: {session.proxy_location}")
print(f"IP Address: {session.ip_address}")

Creating Sessions with Specific Proxies

# Launch browser with specific proxy
browser = await skyvern.launch_cloud_browser(
    proxy_location=ProxyLocation.RESIDENTIAL_JP
)

page = await browser.get_working_page()

# All navigation uses Japan proxy
await page.goto("https://example.jp")
await page.click(prompt="Click login")

session_id = browser.browser_session_id
print(f"Session {session_id} using Japan proxy")

Configuration Options

Environment Variables

For self-hosted deployments:
# Proxy configuration
PROXY_SERVER="http://proxy.example.com:8080"
PROXY_USERNAME="your-username"
PROXY_PASSWORD="your-password"

# Residential proxy zones (Skyvern Cloud)
RESIDENTIAL_PROXY_URL="http://proxy.provider.com"
RESIDENTIAL_PROXY_USERNAME="username"
RESIDENTIAL_PROXY_PASSWORD="password"

Custom Proxy Configuration

from skyvern import Skyvern

# Use custom proxy (self-hosted)
skyvern = Skyvern(
    api_key="your-api-key",
    proxy_server="http://your-proxy.com:8080",
    proxy_username="username",
    proxy_password="password"
)

Best Practices

1. Choose Appropriate Proxy

# Use geographically close proxies for better performance
if target_site.endswith(".co.uk"):
    proxy = ProxyLocation.RESIDENTIAL_GB
elif target_site.endswith(".jp"):
    proxy = ProxyLocation.RESIDENTIAL_JP
else:
    proxy = ProxyLocation.RESIDENTIAL  # Default US

task = await skyvern.run_task(
    prompt="Extract data",
    url=target_site,
    proxy_location=proxy
)

2. Handle Proxy Failures

from skyvern.exceptions import ProxyError

try:
    task = await skyvern.run_task(
        prompt="Extract data",
        url="https://example.com",
        proxy_location=ProxyLocation.RESIDENTIAL_GB
    )
except ProxyError:
    # Retry with different proxy
    task = await skyvern.run_task(
        prompt="Extract data",
        url="https://example.com",
        proxy_location=ProxyLocation.RESIDENTIAL  # Fallback to US
    )

3. Monitor Proxy Performance

import time

proxy_performance = {}

for proxy in [ProxyLocation.RESIDENTIAL_GB, ProxyLocation.RESIDENTIAL_DE]:
    start = time.time()
    
    task = await skyvern.run_task(
        prompt="Quick load test",
        url="https://example.com",
        proxy_location=proxy
    )
    
    duration = time.time() - start
    proxy_performance[proxy] = duration

print("Proxy performance:")
for proxy, duration in proxy_performance.items():
    print(f"{proxy}: {duration:.2f}s")

4. Respect Geo-Restrictions

# Only use proxies for legitimate purposes
# Respect websites' terms of service
# Don't circumvent security measures

# Good: Testing your own multi-region deployment
task = await skyvern.run_task(
    prompt="Test EU version of our site",
    url="https://your-app.eu",
    proxy_location=ProxyLocation.RESIDENTIAL_DE
)

# Be cautious with third-party sites
# Ensure you have permission to access from different regions

Troubleshooting

Proxy Connection Failed

# Check proxy availability
try:
    task = await skyvern.run_task(
        prompt="Test task",
        url="https://example.com",
        proxy_location=ProxyLocation.RESIDENTIAL_JP
    )
except Exception as e:
    if "proxy" in str(e).lower():
        print("Proxy connection failed, trying alternative")
        # Try different proxy or no proxy
        task = await skyvern.run_task(
            prompt="Test task",
            url="https://example.com",
            proxy_location=ProxyLocation.NONE
        )

IP Address Verification

# Verify proxy is working
task = await skyvern.run_task(
    prompt="Extract IP address from page",
    url="https://api.ipify.org?format=json",
    proxy_location=ProxyLocation.RESIDENTIAL_GB,
    data_extraction_schema={"ip": "string"}
)

print(f"Public IP: {task.output['ip']}")
# Should be a UK IP address

Geo-Blocked Content

# If content is still blocked, try more specific location
task = await skyvern.run_task(
    prompt="Access region-locked content",
    url="https://example.com",
    proxy_location=GeoTarget(
        country="GB",
        city="London"  # Try specific city
    )
)

Build docs developers (and LLMs) love