Skip to content
WebUplink

Error Reference

Complete reference for all WebUplink API error codes with resolution steps.

Error Reference

All errors return a consistent JSON shape:

{
  "error": "QUOTA_EXCEEDED",
  "message": "Monthly action quota exhausted (250/250). Upgrade to Builder for 1,000 actions/month with overage, or start a free 14-day Builder trial: https://webuplink.ai/dashboard?upgrade=true",
  "request_id": "req-abc-123"
}

Use error for programmatic handling and request_id for support tickets — include it when emailing support@webuplink.ai. Retryable errors include a retry_after field (seconds) and a Retry-After header.

Error Codes

CodeHTTPRetryableResolution
UNAUTHORIZED401NoCheck API key format and validity
VALIDATION_ERROR400NoCheck request body against the schema
DOMAIN_BLOCKED403NoThe URL is on the restricted list (banking, streaming, ticketing — blocked on every plan), or it's a third-party authentication domain (e.g. accounts.google.com) and login automation isn't enabled on your account. Login automation is a verification-gated capability on all plans — enable it in the dashboard (card on file + AUP attestation): dashboard → billing
SESSION_NOT_FOUND404NoSession may have expired — create a new one
SESSION_BUSY409YesWait for the current request to complete
SESSION_EXPIRED410NoSession timed out (~2min idle or ~15min total) — create a new one
PLAN_RESTRICTED402NoFeature requires a higher plan — upgrade
NO_SUBSCRIPTION402NoSubscribe to access billing features
ALREADY_SUBSCRIBED409NoYou already have an active subscription — change plans from the dashboard instead of starting a new checkout
QUOTA_EXCEEDED429NoAction quota reached. Free: hard cap until the calendar-month reset (or upgrade). Trial: hard cap for the 14-day trial window — subscribe to continue. The body carries a machine-readable upgrade object (see below)
SPEND_CAP_EXCEEDED402NoYour monthly spend cap was reached — raise it in the dashboard to continue
RATE_LIMITED429YesToo many requests — check retry_after field
CONCURRENCY_EXCEEDED503YesAll concurrent session slots for your plan are in use — close a session or retry after retry_after
CONCURRENCY_UNAVAILABLE503YesFree-tier session admission is temporarily unavailable (fail-closed) — retry after retry_after
FREE_TIER_DEGRADED503YesThe free tier's daily budget is exhausted — tool execution resumes at UTC midnight (observation still works). The body carries the upgrade object; upgrading lifts the degradation immediately
AI_PROCESSING_ERROR502YesAI processing failed for this page — retry after retry_after (5s)
SITE_BLOCKED502NoThe site served a bot-verification challenge or an access-denied page instead of real content. The request is not billed and no retry_after is sent — retrying from the same infrastructure hits the same wall. The message names which it was (challenge vs. access denied). See Production Traffic & Bot Detection
BROWSER_ERROR503YesBrowser infrastructure was temporarily unavailable — retry after retry_after (5s)
INTERNAL_ERROR500SometimesUnexpected server error — retry with backoff only if retry_after is present

Not every 502/503 carries these codes. Our load balancer can emit its own 502/503 responses without a JSON body (for example during a deploy or upstream connection failure). The SDKs map those to INTERNAL_ERROR — check for the JSON error field before branching on a code.

Quota errors carry an upgrade CTA

Hard-stop quota responses on the Free and trial plans (QUOTA_EXCEEDED) and free-tier degradation (FREE_TIER_DEGRADED) include a machine-readable upgrade object, so agents and SDKs can surface the exact next step without parsing prose. Quota errors also include a usage snapshot:

{
  "error": "QUOTA_EXCEEDED",
  "message": "Monthly action quota exhausted (250/250). Upgrade to Builder for 1,000 actions/month with overage, or start a free 14-day Builder trial: https://webuplink.ai/dashboard?upgrade=true",
  "request_id": "req-abc-123",
  "usage": {
    "actionCount": 250,
    "actionLimit": 250,
    "periodStart": "2026-07-01T00:00:00.000Z"
  },
  "upgrade": {
    "trial": true,
    "plans": ["builder", "pro"],
    "url": "https://webuplink.ai/dashboard?upgrade=true"
  }
}

upgrade.trial is true when the 14-day Builder trial (card required, auto-converts on day 14, cancel anytime) is available from your current plan — i.e. on Free. Trialists get trial: false with a subscribe message instead.

Handling Errors in the SDK

import { WebUplink, WebUplinkError } from 'webuplink';

const client = new WebUplink({
  apiKey: process.env.WEBUPLINK_API_KEY!,
  baseUrl: 'https://api.webuplink.ai',
});

try {
  const page = await client.browse('https://example.com');
} catch (err) {
  if (err instanceof WebUplinkError) {
    console.log(err.code);       // 'QUOTA_EXCEEDED'
    console.log(err.statusCode); // 429
    console.log(err.requestId);  // 'req-abc-123'
    console.log(err.retryable);  // false
    console.log(err.retryAfter); // undefined

    if (err.retryable && err.retryAfter) {
      // Wait and retry
      await new Promise(r => setTimeout(r, err.retryAfter! * 1000));
    }
  }
}

Retry Behavior

The SDK automatically retries retryable errors with the following rules:

  • Connection errors (network failures) are always retried with linear backoff
  • Server errors with retry_after are retried after the specified wait time
  • 429 responses (RATE_LIMITED, QUOTA_EXCEEDED) are never automatically retried, even with retry_after — auto-retrying a throttle amplifies load
  • SITE_BLOCKED carries no retry_after, so it is never automatically retried
  • Tool execution requests are never automatically retried (non-idempotent)
  • Maximum retry attempts: 3 (configurable via maxRetries option)
// Disable retries entirely
const client = new WebUplink({
  apiKey: '...',
  baseUrl: '...',
  retry: false,
});

Rate Limits

Rate limits are per-tenant, per-minute:

PlanRequests/minute
Free30
Trial120
Builder120
Pro300

Every /v1 response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. When rate limited, the response includes a retry_after field (and Retry-After header) with the number of seconds to wait.

On this page