Skip to main content
Every setting for a self-hosted server is an environment variable in .env. This page covers LLM providers, browser settings, credentials and encryption, other server settings, storage and Kubernetes. For setup, start at Self-host. Skyvern uses LLMs to analyze screenshots and decide what actions to take. Configure at least one LLM provider before running tasks.

How Skyvern uses LLMs

Skyvern makes multiple LLM calls per task step:
  1. Screenshot analysis: Identify interactive elements on the page
  2. Action planning: Decide what to click, type, or extract
  3. Result extraction: Parse data from the page into structured output
A task that runs for 10 steps makes roughly 30+ LLM calls. Choose your provider and model tier with this in mind. For most deployments, configure a single provider using LLM_KEY. Skyvern also supports a SECONDARY_LLM_KEY for lighter tasks to reduce costs.

Quick Start Recommendations

Best models for production (2026):

OpenAI

The most common choice. Requires an API key from platform.openai.com.
.env

Available models

Optional settings

.env

xAI Grok

Grok models from x.ai. Requires an xAI API key.
.env

Available models

Optional settings

.env

Anthropic

Claude models from anthropic.com.
.env

Available models


Azure OpenAI

Microsoft-hosted OpenAI models. Requires an Azure subscription with OpenAI service provisioned.
.env

Setup steps

  1. Create an Azure OpenAI resource in the Azure Portal
  2. Open the Azure AI Foundry portal from your resource’s overview page
  3. Go to Shared Resources → Deployments
  4. Click Deploy Model → Deploy Base Model → select GPT-4o or GPT-4
  5. Note the Deployment Name. Use this for AZURE_DEPLOYMENT
  6. Copy your API key and endpoint from the Azure Portal
The AZURE_DEPLOYMENT is the name you chose when deploying the model, not the model name itself.

Google Gemini

Skyvern supports Gemini through two paths: the Gemini API (simpler, uses an API key) and Vertex AI (enterprise, uses a GCP service account).

Gemini API

The quickest way to use Gemini. Get an API key from Google AI Studio.
.env

Available Gemini API models

Vertex AI

For enterprise deployments through Vertex AI. Requires a GCP project with Vertex AI enabled.
.env
If you’re migrating from an older Skyvern version, VERTEX_LOCATION replaces the previous GCP_REGION variable. Update your .env accordingly.
Vertex AI setup steps:
  1. Create a GCP project with billing enabled
  2. Enable the Vertex AI API in your project
  3. Create a service account with the Vertex AI User role
  4. Download the service account JSON key file
  5. Set VERTEX_CREDENTIALS to the contents of that file as a JSON string. If you leave it unset, Skyvern falls back to Application Default Credentials (for example GOOGLE_APPLICATION_CREDENTIALS or Workload Identity)
For global endpoint access, set VERTEX_LOCATION=global and ensure VERTEX_PROJECT_ID is set. Not all models support the global endpoint.

Available Vertex AI models


Amazon Bedrock

Run Anthropic Claude through your AWS account.
.env

Setup steps

  1. Create an IAM user with AmazonBedrockFullAccess policy
  2. Generate access keys for the IAM user
  3. In the Bedrock console, go to Model Access
  4. Enable access to Claude Opus 4.7

Available models

Bedrock inference profile keys (*_INFERENCE_PROFILE) use cross-region inference and require AWS_REGION only. No access keys needed if running on an IAM-authenticated instance.

VolcEngine (ByteDance Doubao)

VolcEngine provides access to ByteDance’s Doubao models with vision support.
.env

Available models

Optional settings

.env

Novita

Novita AI provides access to DeepSeek, Llama, and other open-source models.
.env

Available models


Moonshot

Moonshot AI provides the Kimi series models with long context support.
.env

Available models

Optional settings

.env

Inception

Inception AI provides the Mercury series models.
.env

Available models

Optional settings

.env

Ollama (Local Models)

Run open-source models locally with Ollama. No API costs, but requires sufficient local compute.
.env

Setup steps

  1. Install Ollama
  2. Pull a model: ollama pull gemma4
  3. Start Ollama: ollama serve
  4. Configure Skyvern to connect
Most Ollama models don’t support vision. Set OLLAMA_SUPPORTS_VISION=false. Without vision, Skyvern relies on DOM analysis instead of screenshot analysis, which may reduce accuracy on complex pages.

Docker networking

When running Skyvern in Docker and Ollama on the host:

OpenAI-Compatible Endpoints

Connect to any service that implements the OpenAI API format, including LiteLLM, LocalAI, vLLM, and text-generation-inference.
.env
This is useful for:
  • Running local models with a unified API
  • Using LiteLLM as a proxy to switch between providers
  • Connecting to self-hosted inference servers

OpenRouter

Access multiple models through a single API at openrouter.ai.
.env

Groq

Inference on open-source models at groq.com.
.env
Groq specializes in fast inference for open-source models. Response times are typically much faster than other providers, but model selection is limited.

Using multiple models

Primary and secondary models

Configure a cheaper model for lightweight operations:
.env
Recommended primary models (latest):
  • Anthropic Claude 4.7 Opus (ANTHROPIC_CLAUDE4.7_OPUS) - Most capable
  • OpenAI GPT-5.5 (OPENAI_GPT5_5) - Latest
  • Google Gemini 3 Pro (GEMINI_3_PRO) - Latest
Recommended secondary models (latest):
  • Claude 4.6 Sonnet (ANTHROPIC_CLAUDE4.6_SONNET) - Balanced
  • GPT-5.4 (OPENAI_GPT5_4) - Fast reasoning
  • Gemini 3.0 Flash (GEMINI_3.0_FLASH) - Faster Gemini 3

Task-specific models

For fine-grained control, you can override models for specific operations:
.env
Most deployments don’t need task-specific models. Start with LLM_KEY and SECONDARY_LLM_KEY.

Troubleshooting

”To enable svg shape conversion, please set the Secondary LLM key”

Some operations require a secondary model. Set SECONDARY_LLM_KEY in your environment:
.env

“Context window exceeded”

The page content is too large for the model’s context window. Options:
  • Use a model with larger context support (GPT-5.5, Gemini 2.5 Pro, or Claude 4.7 Opus)
  • Simplify your prompt to require less page analysis
  • Start from a more specific URL with less content

”Environment variables LLM_API_KEY are required for LLMProvider …”

The configured LLM_KEY doesn’t match any enabled provider, so Skyvern treats it as a generic model name and asks for LLM_API_KEY. Verify:
  1. The provider is enabled (ENABLE_OPENAI=true, etc.)
  2. The LLM_KEY value matches a supported model name exactly
  3. Model names are case-sensitive: OPENAI_GPT5_5 not openai_gpt5_5

Container logs show authentication errors

Check your API key configuration:
  • Ensure the key is set correctly without extra whitespace
  • Verify the key hasn’t expired or been revoked
  • For Azure, ensure AZURE_API_BASE includes the full URL with https://

Slow response times

LLM calls typically take 2-10 seconds. Longer times may indicate:
  • Network latency to the provider
  • Rate limiting (the provider may be throttling requests)
  • For Ollama, insufficient local compute resources

Browser settings

Set these in .env (or the backend secret on Kubernetes) and restart the server. For the choice between headful, headless and cdp-connect, see Self-host. Match BROWSER_LOCALE and BROWSER_TIMEZONE to the region the site expects. A mismatch can trigger bot detection. Each concurrent run uses its own browser. Approximate memory: On out-of-memory errors, lower BROWSER_MAX_PAGES_NUMBER, shrink the viewport, switch to chromium-headless, or run fewer runs at once.

Connect your own Chrome (CDP)

Start your installed Chrome. Set BROWSER_TYPE=cdp-connect and CHROME_EXECUTABLE_PATH. Skyvern copies your profile to ./tmp/user_data_dir, launches Chrome with remote debugging on port 9222, and connects. Close every Chrome window first; if Chrome is already running, Skyvern returns an error. If port 9222 is already in use, Skyvern connects to that instance instead. Connect to a Chrome that is already running. In Chrome, open chrome://inspect/#remote-debugging and turn on remote debugging. Skyvern auto-discovers a local debugging server, or accepts a pasted ws://.../devtools/browser/... URL. skyvern init browser walks you through it. If Skyvern runs in Docker and can’t reach Chrome’s loopback listener, start a separate profile on a reachable address. Since Chrome 136, --remote-debugging-port is ignored for the default profile, so always pass --user-data-dir:
If Chrome rejects the host.docker.internal host name, Skyvern retries with the Docker host gateway IPv4 address. On Windows with Docker Desktop, the chrome://inspect listener is loopback only. From an Administrator PowerShell in the Skyvern repo, run .\scripts\windows_chrome_inspect_cdp.ps1 -UpdateEnv, then docker compose up -d --force-recreate skyvern. The helper proxies 0.0.0.0:9223 to Chrome, adds a firewall rule, and writes BROWSER_REMOTE_DEBUGGING_URL=ws://host.docker.internal:9223/devtools/browser/<id> and BROWSER_REMOTE_DEBUGGING_HOST_HEADER to .env. Click Allow if Chrome asks to allow the connection. If Windows Firewall blocks port 9222 for a classic endpoint:
Check a classic endpoint with curl http://localhost:9222/json/version. It returns Chrome’s version and a webSocketDebuggerUrl.
--remote-debugging-address=0.0.0.0 exposes Chrome to the network. Use it only on a trusted network. Outside Docker, bind to 127.0.0.1.

Credentials and encryption

CREDENTIAL_VAULT_TYPE picks where new credentials are stored. Restart the server after changing it.

Bitwarden and Vaultwarden

Skyvern doesn’t call Bitwarden directly. It talks to a Bitwarden CLI server (bw serve), which is logged in to your vault and unlocked. Self-hosted Vaultwarden. The open-source docker-compose.yml ships two commented-out services: vaultwarden (the server, on 127.0.0.1:11002) and bitwarden-cli (built from bitwarden-cli-server/). To use them:
  1. Uncomment vaultwarden, start it, sign up, and create your master password and an organization. Then set SIGNUPS_ALLOWED: "false".
  2. In Vaultwarden, copy the API client ID and secret.
  3. Uncomment bitwarden-cli and set its environment. It runs bw config server, logs in with the API key, unlocks, and serves on port 8087, published as 127.0.0.1:8002.
  4. Set CREDENTIAL_VAULT_TYPE=bitwarden and the SKYVERN_AUTH_BITWARDEN_* values on the Skyvern server (same API key and password). Point BITWARDEN_SERVER at the CLI server: http://localhost and port 8002 from the host, or http://bitwarden-cli and port 8087 from another container in the same Compose project.
  5. Check it: curl http://localhost:8002/status returns the vault status.

Encryption at rest

With ENABLE_ENCRYPTION=true, Skyvern encrypts stored secrets such as organization tokens and OAuth refresh tokens. The Google integrations require it.
Never change ENCRYPTOR_AES_SECRET_KEY, ENCRYPTOR_AES_SALT or ENCRYPTOR_AES_IV after secrets are stored. Skyvern can’t decrypt anything stored under the old values.

Other server settings

URL validation

URL validation is off by default, so Skyvern can open, fetch and call internal hosts without extra setup. That includes an intranet portal, a service on your network and localhost. Set ENABLE_URL_VALIDATION=true if people you don’t trust can start tasks or workflows on your server, or if it runs next to internal services or a cloud metadata endpoint. When it is on, Skyvern refuses a URL if its host is localhost, a name ending in .local, .localhost, .internal, .svc or .cluster.local, or an address in a loopback, private (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local (169.254.0.0/16, which includes the cloud metadata address), shared (100.64.0.0/10), reserved, multicast or unspecified range. Names are checked after DNS resolution, so a public name that resolves to a private address is refused too. The check covers the URLs a run or workflow gives Skyvern: page navigation and link clicks, downloads, webhooks, 2FA callbacks, and SFTP, SMTP and S3-compatible endpoints. SFTP, SMTP and S3 targets also have their own ALLOW_SFTP_INTERNAL_HOSTS, ALLOW_SMTP_INTERNAL_HOSTS and ALLOW_S3_ENDPOINT_INTERNAL_HOSTS switches (the S3 one also allows plain http:// endpoints). With validation on, list the hosts you want to keep reachable in ALLOWED_HOSTS, a JSON list of exact host names or IP addresses such as ALLOWED_HOSTS=["intranet.example.com"]. BLOCKED_HOSTS adds hosts to refuse.
Whoever can start a task chooses the URLs Skyvern fetches. With validation off, they can point Skyvern at anything your server can reach. Turn it on before you share a server with people you don’t trust.

Storage

SKYVERN_STORAGE_TYPE picks where artifacts go. Each cloud backend uses four buckets (containers on Azure). The defaults are skyvern-artifacts, skyvern-screenshots, skyvern-browser-sessions and skyvern-uploads. Docker Compose mounts ./artifacts, ./videos, ./har and ./log next to docker-compose.yml. Local storage isn’t shared between servers and is never cleaned up; delete old files yourself, for example find ./artifacts -type f -mtime +30 -delete.

AWS S3

.env
Credentials come from the standard AWS chain: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, an IAM role on EC2, ECS or EKS, or AWS_PROFILE set in the container’s environment. Create the buckets first. Bucket names are global, so add a unique prefix.
Minimum IAM policy:
Expire old artifacts with a lifecycle rule:
Turn on server-side encryption and access logging on the buckets as your policies require. On “Access Denied”, check the policy, that the buckets exist, and that AWS_REGION matches the bucket region.

Azure Blob Storage

.env
The account key is required. Managed identity isn’t supported, and Skyvern raises an error without the key.
Use an Azure lifecycle management policy to expire old blobs.

Google Cloud Storage

.env
Authentication uses Application Default Credentials: Workload Identity on GKE, or GOOGLE_APPLICATION_CREDENTIALS pointing at a service-account key. Create the buckets first.

Move existing local artifacts

Changing SKYVERN_STORAGE_TYPE only affects new artifacts. To copy old ones, sync them once, then switch and restart:
If artifacts don’t appear, check docker compose logs skyvern | grep -i storage.

Kubernetes

The manifests in kubernetes-deployment/ create a skyvern namespace with postgres, skyvern-backend (API and browser, port 8000) and skyvern-frontend (UI on 8080, artifacts on 9090), plus a Traefik ingress routing /api to the backend, /artifacts to 9090 and / to the UI. Any ingress controller works; change ingressClassName. After ./k8s-deploy.sh, wait for the backend pod to show 1/1 (migrations take 1–2 minutes), then read the API key and give it to the UI:
Persistent volumes. The backend uses hostPath volumes, which only work on a single node. For production, replace them with PVCs in backend/backend-deployment.yaml, or use S3, Azure Blob or GCS:
Scaling and limits. Raise replicas on the backend deployment to run more pods; each runs its own browser. With more than one pod, storage must be shared (S3, Azure Blob, GCS or ReadWriteMany volumes). Give each backend pod at least 2 GB:
TLS. Uncomment the tls section in ingress.yaml and create the secret (or use cert-manager), then switch the frontend URLs to https:// and wss://:
External database. Drop the postgres/ manifests and set DATABASE_STRING: "postgresql+psycopg://user:password@your-db-host:5432/skyvern" in the backend secret. The manifests have no authentication. Add it at the ingress, or keep the cluster off the public internet. kubectl delete namespace skyvern removes everything.