API Reference

Complete reference for every PageBolt endpoint, parameter, and integration.

Quick Start

Get your first screenshot in under 5 minutes. Three steps:

1

Sign up free

Create an account at pagebolt.dev/signup. No credit card required — you get 100 requests/month on all 7 APIs.

2

Get your API key

Your API key is generated automatically when you verify your email. Find it in the Dashboard.

3

Make your first API call

Copy this cURL command, replace YOUR_API_KEY, and run it:

Your first screenshot
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "format": "webp"}' \
  -o screenshot.webp
Don't want to sign up yet? Try the sandbox — 5 free screenshots per day, no account needed.

What's next?

Authentication

All API requests require an API key. Pass it via the x-api-key header. For security, query parameter authentication is not supported — API keys should never appear in URLs, logs, or browser history.

Header authentication
curl -H "x-api-key: pf_live_your_key_here" \
  https://pagebolt.dev/api/v1/screenshot
Tip: Want to try it first? Test it free in your browser—no signup required. When you're ready, get your API key from the Dashboard. The free plan includes 100 requests/month, or choose Pay As You Go to pay only for what you use—both with no credit card required to start.

Base URL

https://pagebolt.dev/api/v1

All endpoint paths in this documentation are relative to this base URL.

Error Responses

All errors return JSON with an error field.

StatusMeaning
400Bad request — check your parameters
401Invalid or missing API key
402Quota exceeded (subscription) or insufficient balance (PAYG) — upgrade or top up
429Rate limit exceeded — slow down
500Server error — try again or contact support
Example error response
{
  "error": "Either \"url\", \"html\", or \"markdown\" is required"
}

Rate Limits

Rate limits are per-user, based on your plan. Check response headers:

HeaderDescription
X-RateLimit-LimitRequests per minute allowed
X-RateLimit-RemainingRequests remaining this window
X-Usage-CurrentRequests used this month
X-Usage-LimitMonthly request limit
POST

/v1/screenshot

Capture a screenshot of a URL, raw HTML, or Markdown content. Returns the image as binary data (or base64 JSON with metadata).

Input

ParameterTypeDefaultDescription
urlstringURL to capture (required if no html or markdown)
htmlstringRaw HTML to render
markdownstringMarkdown to render NEW

Viewport

ParameterTypeDefaultDescription
widthinteger1280Viewport width in pixels (max 3840)
heightinteger720Viewport height in pixels (max 2160)
deviceScaleFactornumber1Device pixel ratio, use 2 for retina (max 3)
viewportDevicestringDevice preset, e.g. "iphone_14_pro". Overrides width/height/DPR. NEW
viewportMobilebooleanfalseEnable mobile meta viewport NEW
viewportHasTouchbooleanfalseEnable touch events NEW
viewportLandscapebooleanfalseEnable landscape mode NEW

Output

ParameterTypeDefaultDescription
formatstringpngpng, jpeg, or webp
qualityinteger80JPEG/WebP quality 1–100
fullPagebooleanfalseCapture the full scrollable page
selectorstringCSS selector for element capture
omitBackgroundbooleanfalseTransparent background (PNG/WebP only) NEW
clipobjectCrop region {x, y, width, height} in pixels NEW

Full Page Controls NEW

ParameterTypeDefaultDescription
fullPageScrollbooleanautoAuto-scroll to trigger lazy-loaded images before capture
fullPageScrollDelayinteger400Milliseconds to wait between scroll steps
fullPageScrollByintegerviewport heightPixels per scroll step
fullPageMaxHeightintegerMaximum screenshot height cap in pixels

Timing

ParameterTypeDefaultDescription
delayinteger0Wait ms before capture (max 10000)
waitUntilstringnetworkidle2load, domcontentloaded, networkidle0, networkidle2 NEW
waitForSelectorstringWait for a CSS selector to appear before capturing NEW
navigationTimeoutinteger25000Navigation timeout in milliseconds NEW

Emulation NEW

ParameterTypeDefaultDescription
darkModebooleanfalseEmulate dark color scheme (prefers-color-scheme: dark)
reducedMotionbooleanfalseReduce animations (prefers-reduced-motion)
mediaTypestring"screen" or "print"
timeZonestringTimezone ID, e.g. "America/New_York"
geolocationobject{latitude, longitude, accuracy?}

Customization

ParameterTypeDefaultDescription
userAgentstringCustom User-Agent string NEW
cookiesarrayArray of "name=value" strings or {name, value, domain?} objects NEW
headersobjectExtra HTTP headers to send with the page request NEW
authorizationstringAuthorization header value, e.g. "Bearer <token>" NEW
authStateobjectFull browser auth state — injects cookies and localStorage before navigation. Use the Auth State Extractor to capture this from your browser. NEW
bypassCSPbooleanfalseBypass Content-Security-Policy on the page NEW
hideSelectorsarrayCSS selectors to hide before capture NEW
clickstringClick a CSS selector before capture NEW
injectCssstringCustom CSS to inject into the page
injectJsstringCustom JavaScript to execute before capture

Blocking

ParameterTypeDefaultDescription
blockBannersbooleanfalseHide cookie consent banners (GDPR popups, OneTrust, CookieBot, etc.)
blockAdsbooleanfalseBlock advertisements NEW
blockChatsbooleanfalseBlock live chat widgets (Intercom, Crisp, Drift, etc.) NEW
blockTrackersbooleanfalseBlock analytics trackers (GA, Hotjar, Segment, etc.) NEW
blockRequestsarrayURL patterns to block (substring match) NEW
blockResourcesarrayResource types to block: document, stylesheet, image, media, font, script, xhr, fetch, etc. NEW

Anti-Detection & Proxy NEW

ParameterTypeDefaultDescription
stealthbooleanfalseMask browser fingerprints to bypass bot detection walls. Uses an ephemeral browser instance per request.
proxystringRoute requests through your proxy. Format: "http://user:pass@host:port". Supports http, https, socks4, socks5.

Both parameters are supported on Screenshot, PDF, Sequence, and Video endpoints.

Metadata NEW

ParameterTypeDefaultDescription
extractMetadatabooleanfalseExtract page metadata (title, description, OG tags, favicon, HTTP status, canonical, lang)

Response Format

ParameterTypeDefaultDescription
response_typestringbinarySet to "json" for base64-encoded response with metadata

When response_type is "json" and extractMetadata is true, the response includes:

JSON response with metadata
{
  "data": "iVBORw0KGgo...",
  "format": "png",
  "content_type": "image/png",
  "size_bytes": 284512,
  "duration_ms": 1243,
  "metadata": {
    "title": "Page Title",
    "description": "Meta description",
    "ogTitle": "OG Title",
    "ogDescription": "OG Description",
    "ogImage": "https://example.com/og.png",
    "ogType": "website",
    "favicon": "/favicon.ico",
    "httpStatusCode": 200,
    "canonical": "https://example.com",
    "lang": "en"
  }
}
Default response: Binary image data with the appropriate Content-Type header (image/png, image/jpeg, or image/webp). Status 200 on success.

Styling (Post-Processing)

Add presentation-ready styling to your screenshots — curated theme presets, gradient backgrounds, glassmorphism, neon glows, noise textures, and more. Pass a style object to apply post-capture beautification.

Theme Presets NEW

Use style.theme for a one-param curated style. Themes set frame, background, shadow, padding, and border radius automatically. You can override any individual property alongside the theme.

ThemeFrameBackgroundTier
notionmacOS lightSolid warm whiteFree
paperNoneSolid whiteFree
vercelNoneSolid blackFree
glassMinimalFrosted glassFree
oceanmacOSOcean gradientFree
sunsetmacOSSunset gradientFree
linearMinimalMidnight gradientStarter+
arcmacOSAurora gradientStarter+
glassDarkNoneDark frosted glassStarter+
glassWarmNoneWarm frosted glassStarter+
spotlightNoneRadial spotlightStarter+
neonBlueMinimalMidnight + blue glowStarter+
neonPurpleMinimalMidnight + purple glowStarter+
neonGreenMinimalSlate + green glowStarter+
lavendermacOSLavender gradientStarter+
emberMinimalEmber gradientStarter+
dotsMinimalDot grid patternStarter+
gridMinimalGrid line patternStarter+

Manual Style Parameters

ParameterTypeDefaultDescription
style.themestringTheme preset name (see table above). Sets all style properties at once. Individual overrides still apply. NEW
style.framestringnonemacos, windows, minimal, or none. Adds a browser chrome bar above the screenshot.
style.frameThemestringdarklight, dark, or auto. Controls the frame bar color scheme.
style.backgroundstringnoneGradient preset: ocean, sunset, forest, midnight, aurora, lavender, peach, arctic, ember, slate, neon. Special: glass (frosted), spotlight, dots, grid, noise, solid, or none.
style.bgColorstring#1e3a5fHex color for solid background, e.g. "#1e3a5f".
style.bgColorsarrayCustom gradient: array of exactly 2 hex colors, e.g. ["#667eea","#764ba2"]. Overrides preset.
style.paddinginteger40Padding around the screenshot in pixels (0–120).
style.borderRadiusinteger12Corner radius in pixels (0–40).
style.shadowstringmdnone, xs, sm, md, lg, xl, or 2xl. Drop shadow intensity.
Tip: Use { "style": { "theme": "linear" } } for instant polished results. The glass background creates a frosted glassmorphism effect using a blurred version of the screenshot itself as the backdrop. The neon* themes add a colored glow border and shadow — great for dark-mode hero images.

Styled screenshot example

cURL
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://my-saas.com",
    "format": "png",
    "style": {
      "frame": "macos",
      "background": "ocean",
      "shadow": "lg",
      "padding": 60,
      "borderRadius": 16
    }
  }' \
  -o styled-screenshot.png

Example 1: Basic screenshot

cURL
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://my-saas.com",
    "width": 1280,
    "height": 720,
    "format": "png",
    "fullPage": false
  }' \
  -o screenshot.png

Example 2: Device preset + dark mode

cURL
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://my-saas.com",
    "viewportDevice": "iphone_15_pro_max",
    "darkMode": true,
    "format": "webp",
    "quality": 90
  }' \
  -o linear-mobile-dark.webp

Example 3: Metadata extraction

Node.js
const res = await fetch('https://pagebolt.dev/api/v1/screenshot', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.PAGEBOLT_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://my-saas.com',
    extractMetadata: true,
    response_type: 'json',
    format: 'webp',
  }),
});

const { data, metadata } = await res.json();
console.log(metadata.title);       // "My SaaS — Dashboard"
console.log(metadata.ogImage);     // "https://my-saas.com/og.png"
console.log(metadata.httpStatusCode); // 200

// Save the screenshot
const buf = Buffer.from(data, 'base64');
fs.writeFileSync('my-saas.webp', buf);

Example 4: Ad blocking + transparent background

Python
import requests, os

resp = requests.post(
    "https://pagebolt.dev/api/v1/screenshot",
    headers={
        "x-api-key": os.environ["PAGEBOLT_KEY"],
        "Content-Type": "application/json",
    },
    json={
        "url": "https://my-blog.com",
        "blockAds": True,
        "blockBanners": True,
        "blockChats": True,
        "blockTrackers": True,
        "omitBackground": True,
        "format": "png",
    },
)

with open("clean-screenshot.png", "wb") as f:
    f.write(resp.content)

Example 5: Full page with lazy image scroll

cURL
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.apple.com/iphone",
    "fullPage": true,
    "fullPageScroll": true,
    "fullPageScrollDelay": 500,
    "fullPageMaxHeight": 15000,
    "format": "jpeg",
    "quality": 85
  }' \
  -o apple-fullpage.jpg

Example 6: Geolocation and timezone

cURL
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://weather.com",
    "timeZone": "Asia/Tokyo",
    "geolocation": {
      "latitude": 35.6762,
      "longitude": 139.6503,
      "accuracy": 100
    },
    "width": 1440,
    "height": 900,
    "darkMode": true
  }' \
  -o weather-tokyo.png

Example 7: Authenticated page with cookies & headers

Node.js
const res = await fetch('https://pagebolt.dev/api/v1/screenshot', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.PAGEBOLT_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://myapp.com/dashboard',
    cookies: [
      { name: 'session', value: 'abc123xyz', domain: 'myapp.com' },
      { name: 'theme', value: 'dark', domain: 'myapp.com' },
    ],
    headers: {
      'Accept-Language': 'en-US',
    },
    authorization: 'Bearer eyJhbGciOiJIUzI1NiIs...',
    waitForSelector: '.dashboard-loaded',
    darkMode: true,
  }),
});

const screenshot = Buffer.from(await res.arrayBuffer());
fs.writeFileSync('dashboard.png', screenshot);

Authenticated Recording

Recording pages behind OAuth, SSO, or session-based auth requires injecting your existing browser session into Pagebolt. The authState parameter handles this for all endpoints — /screenshot, /video, /sequence, and /inspect.

Key insight: You don't need to automate the login flow. After you've logged into your app normally in Chrome, your browser holds the session state. The authState parameter lets you hand that session to Pagebolt so it starts already authenticated.

The authState format

JSON
{
  "authState": {
    "cookies": [
      {
        "name": "session_id",
        "value": "abc123xyz",
        "domain": "myapp.com",
        "path": "/",
        "secure": true,
        "httpOnly": true
      }
    ],
    "localStorage": [
      {
        "origin": "https://myapp.com",
        "items": [
          { "name": "access_token", "value": "eyJhbGciOiJIUzI1NiIs..." },
          { "name": "user_id", "value": "usr_abc123" }
        ]
      }
    ]
  }
}

Step 1 — Extract your session

Log into your app in Chrome, then open DevTools (F12) and paste this snippet into the Console tab. It extracts your cookies and localStorage into the exact authState format and copies it to your clipboard.

DevTools Console snippet — paste and press Enter
(function() {
  var origin = location.origin;
  var cookies = document.cookie.split(';').filter(Boolean).map(function(c) {
    var parts = c.trim().split('=');
    var name = parts[0].trim();
    var value = parts.slice(1).join('=').trim();
    return { name: name, value: value, domain: location.hostname };
  });
  var lsItems = Object.keys(localStorage).map(function(k) {
    return { name: k, value: localStorage.getItem(k) };
  });
  var authState = {
    cookies: cookies,
    localStorage: [{ origin: origin, items: lsItems }]
  };
  var json = JSON.stringify({ authState: authState }, null, 2);
  console.log(json);
  try { copy(json); console.log('%c✓ Copied to clipboard', 'color: #4ade80'); }
  catch(e) { console.log('%c↑ Copy the JSON above', 'color: #facc15'); }
})();
Note: Browsers block JavaScript from reading HttpOnly cookies by design. If your app uses only HttpOnly session cookies, use the Pagebolt Chrome extension instead — it has access to all cookies including HttpOnly ones.

Step 2 — Pass it to the API

Node.js — record authenticated dashboard demo
const res = await fetch('https://pagebolt.dev/api/v1/video', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.PAGEBOLT_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    steps: [
      { action: 'navigate', url: 'https://myapp.com/dashboard' },
      { action: 'click', selector: '.sidebar-nav-reports', note: 'Open reports' },
      { action: 'scroll', y: 400 },
    ],
    authState: {
      cookies: [
        { name: 'session_id', value: 'abc123xyz', domain: 'myapp.com' }
      ],
      localStorage: [
        {
          origin: 'https://myapp.com',
          items: [
            { name: 'access_token', value: 'eyJhbGciOiJIUzI1NiIs...' }
          ]
        }
      ]
    },
    format: 'mp4',
    pace: 'slow',
    cursor: { style: 'highlight' },
  }),
});

const result = await res.json();
// result.data is base64-encoded MP4

Using the Chrome extension

The Pagebolt Chrome extension has a Capture Auth button in its side panel. Click it while on your logged-in app and your full session state — including HttpOnly cookies — is captured automatically and included in every recording you make from the extension.

GET

/v1/screenshot

Convenience endpoint — pass all parameters as query strings. Ideal for embedding in <img> tags or opening directly in a browser.

Note: Same parameters as POST, but passed via query string. The url parameter is required. Booleans are "true" / "false" strings. Array params like hideSelectors can be repeated (e.g. hideSelectors=.ad&hideSelectors=.banner).
cURL with x-api-key header (GET)
curl -H "x-api-key: pf_live_your_key" \
  "https://pagebolt.dev/api/v1/screenshot?\
url=https://my-saas.com&\
viewportDevice=iphone_14_pro&\
blockBanners=true&\
blockAds=true&\
format=webp" \
  -o my-saas-mobile.webp
NEW

Signed Embed Screenshot URLs

Generate HMAC-signed URLs that render a screenshot and can be placed directly in an <img> tag — no backend proxy required. Starter plan and above.

The signature binds all parameters — changing any part of the URL invalidates it. Expiry is enforced server-side (max 7 days).

How it works: Call POST /dashboard/sign-screenshot from your backend to get a signed URL. Embed that URL in your HTML. When the browser loads the image, PageBolt verifies the signature and serves the screenshot — your API key is never exposed to the browser.

Step 1 — Generate the signed URL (server-side)

cURL
curl -X POST https://pagebolt.dev/dashboard/sign-screenshot \
  -H "Authorization: Bearer YOUR_JWT_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "params": {
      "url": "https://example.com",
      "fullPage": "true",
      "blockBanners": "true",
      "format": "png"
    },
    "expiry_hours": 24
  }'

Response

JSON
{
  "url": "https://pagebolt.dev/api/v1/embed/screenshot?url=https%3A%2F%2Fexample.com&fullPage=true&blockBanners=true&format=png&_key=pf_live_abc123&_exp=1740528000&_sig=a3f9e2...",
  "expires_at": "2026-02-26T12:00:00.000Z",
  "key_prefix": "pf_live_abc123"
}

Step 2 — Embed in HTML

HTML
<img src="https://pagebolt.dev/api/v1/embed/screenshot?url=...&_key=...&_exp=...&_sig=..." alt="Screenshot" />

Parameters

FieldTypeDescription
paramsobjectScreenshot parameters. url is required. Same options as POST /screenshot (all values as strings).
expiry_hoursnumberHow long the URL is valid. Default: 24. Max: 168 (7 days).
Plan required: Signed embed URLs are available on Starter plan and above. Each embed URL render counts as 1 request toward your monthly quota.
POST

/v1/style

NEW

Apply styling (frame, background, shadow, theme) to an existing screenshot image. Accepts a base64-encoded image and returns the styled result. Does not count toward your monthly quota — this endpoint performs image processing only, no browser rendering.

Free styling iterations: Use this endpoint to experiment with different themes and frames on the same screenshot without additional API costs. Capture once, style many times.
Request
curl -X POST https://pagebolt.dev/api/v1/style \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "iVBORw0KGgo...base64-encoded-screenshot...",
    "format": "png",
    "style": {
      "theme": "ocean"
    }
  }'

Parameters

ParameterTypeRequiredDescription
imagestringYesBase64-encoded image data (PNG, JPEG, or WebP). Max 10MB.
formatstringNoOutput format: png, jpeg, webp. Default: png
styleobjectYesStyle configuration. Use theme for presets, or set individual properties.
style.themestringNoTheme preset name: notion, ocean, sunset, linear, arc, etc. See Screenshot API for full list.
style.framestringNomacos, windows, minimal, or none
style.backgroundstringNoBackground preset: ocean, sunset, glass, solid, dots, grid, etc.
style.shadowstringNonone, xs, sm, md, lg, xl, 2xl
style.paddingintegerNoPadding in pixels (0–120). Default: 40
style.borderRadiusintegerNoCorner radius in pixels (0–40). Default: 12
style.bgColorstringNoHex color for solid background, e.g. #1e3a5f
response_typestringNojson returns base64 JSON. Default: binary image.

Response

Binary image by default. If response_type: "json":

JSON Response
{
  "data": "iVBORw0KGgo...base64...",
  "format": "png",
  "content_type": "image/png",
  "size_bytes": 245120,
  "duration_ms": 340
}
POST

/v1/pdf

Generate a PDF from a URL or HTML content. Returns the PDF as binary data.

Parameters

ParameterTypeDefaultDescription
urlstringURL to render (required if no html)
htmlstringRaw HTML to render (required if no url)
formatstringA4Paper format: A4, Letter, Legal, Tabloid
landscapebooleanfalseLandscape orientation
printBackgroundbooleantrueInclude CSS backgrounds
marginstringCSS margin for all sides (e.g. "1cm")
marginsobject{top, right, bottom, left} in CSS units
displayHeaderFooterbooleanfalseShow header and footer
headerTemplatestringHTML template for header
footerTemplatestringHTML template for footer
scalenumber1Rendering scale (0.1–2)
pageRangesstringe.g. "1-5, 8"
widthintegerViewport width for rendering
delayinteger0Wait ms before rendering (max 10000)
response_typestringbinarySet to "json" for base64 response

Example 8: Generate an invoice PDF

cURL
curl -X POST https://pagebolt.dev/api/v1/pdf \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Invoice #1234</h1><p>Amount: $99.00</p>",
    "format": "A4",
    "margin": "2cm",
    "printBackground": true,
    "displayHeaderFooter": true,
    "footerTemplate": "<div style=\"font-size:10px;text-align:center;width:100%\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>"
  }' \
  -o invoice.pdf
POST

/v1/og-image

Generate dynamic Open Graph / social card images. Use built-in templates or provide custom HTML.

Parameters

ParameterTypeDefaultDescription
templatestringdefaultdefault, minimal, or gradient
htmlstringCustom HTML template (overrides template)
titlestringMain title text
subtitlestringSubtitle text
logostringLogo image URL
bgColorstring#0f172aBackground color (hex)
textColorstring#f8fafcText color (hex)
accentColorstring#6366f1Accent color (hex)
bgImagestringBackground image URL
widthinteger1200Image width (max 2400)
heightinteger630Image height (max 1260)
formatstringpngpng, jpeg, or webp
response_typestringbinarySet to "json" for base64 response

Example 9: Create a social card

cURL
curl -X POST https://pagebolt.dev/api/v1/og-image \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "gradient",
    "title": "How to Build a SaaS in 2026",
    "subtitle": "A practical guide for solo founders",
    "accentColor": "#8b5cf6",
    "bgColor": "#1e1b4b",
    "logo": "https://mysite.com/logo.png"
  }' \
  -o social-card.png
POST

/v1/sequence

New

Execute a multi-step browser automation sequence. Navigate pages, interact with elements (click, fill forms, scroll), and capture multiple screenshots and PDFs in a single browser session. Local URLs are not supported — Puppeteer runs on our servers, not yours. To record a local dev server, expose it first with ngrok http 3000 and use the public ngrok URL.

Unique to PageBolt: Unlike other screenshot APIs that return one image per request, Sequences let you chain actions and collect multiple outputs from a single browser context — perfect for capturing multi-step flows, authenticated pages, and before/after comparisons.

Top-Level Parameters

ParameterTypeDefaultDescription
stepsarrayRequired. Array of step objects (max 20)
viewportobject{width, height} — default 1280×720
darkModebooleanfalseEmulate dark color scheme
blockBannersbooleanfalseAuto-hide cookie consent banners
deviceScaleFactornumber1Pixel ratio (max 3, use 2 for retina)

Available Actions

ActionRequired FieldsDescription
navigateurlGo to a URL (http/https only)
clickselectorClick an element by CSS selector
fillselector, valueClear and type into an input field
selectselector, valueSelect a dropdown option by value
hoverselectorHover over an element (reveals tooltips, dropdowns)
scrollselector or x, yScroll to element or absolute position
waitmsWait fixed milliseconds (max 10000)
wait_forselectorWait for element to appear and become visible (optional timeout, max 15s)
evaluatescriptRun JavaScript in page context (max 5000 chars, max 2 per sequence)
screenshotnameCapture current state. Optional: format, fullPage, quality, selector, style
pdfnameGenerate PDF. Optional: format (A4, Letter, Legal, Tabloid, A3, A5), landscape, margin, scale
Limits: Max 20 steps · Max 5 outputs (screenshot + pdf) · Max 2 evaluate steps · 60s total timeout · 15s per-step timeout. Each output counts as 1 API request against your quota.
Styled screenshots in sequences: Add a style object to any screenshot step to apply post-capture styling (frames, backgrounds, shadows, themes). Uses the same options as the Screenshot API style parameter. Example: { "action": "screenshot", "name": "hero", "style": { "theme": "ocean" } }

Example 10: Capture a login flow

cURL
curl -X POST https://pagebolt.dev/api/v1/sequence \
  -H "x-api-key: pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      {"action": "navigate", "url": "https://example.com/login"},
      {"action": "screenshot", "name": "login-page"},
      {"action": "fill", "selector": "#email", "value": "user@example.com"},
      {"action": "fill", "selector": "#password", "value": "demo123"},
      {"action": "click", "selector": "button[type=submit]"},
      {"action": "wait_for", "selector": ".dashboard", "timeout": 5000},
      {"action": "screenshot", "name": "dashboard", "fullPage": true}
    ],
    "viewport": {"width": 1440, "height": 900},
    "blockBanners": true
  }'

Response

JSON
{
  "outputs": [
    {
      "name": "login-page",
      "type": "screenshot",
      "format": "png",
      "content_type": "image/png",
      "data": "iVBORw0KGgo...",
      "size_bytes": 145832,
      "step_index": 1,
      "duration_ms": 342
    },
    {
      "name": "dashboard",
      "type": "screenshot",
      "format": "png",
      "content_type": "image/png",
      "data": "iVBORw0KGgo...",
      "size_bytes": 287654,
      "step_index": 6,
      "duration_ms": 521
    }
  ],
  "step_results": [
    {"step_index": 0, "action": "navigate", "status": "ok", "duration_ms": 2341},
    {"step_index": 1, "action": "screenshot", "status": "ok", "name": "login-page", "duration_ms": 342},
    {"step_index": 2, "action": "fill", "status": "ok", "duration_ms": 87},
    {"step_index": 3, "action": "fill", "status": "ok", "duration_ms": 92},
    {"step_index": 4, "action": "click", "status": "ok", "duration_ms": 45},
    {"step_index": 5, "action": "wait_for", "status": "ok", "duration_ms": 1823},
    {"step_index": 6, "action": "screenshot", "status": "ok", "name": "dashboard", "duration_ms": 521}
  ],
  "steps_completed": 7,
  "total_steps": 7,
  "total_duration_ms": 5251,
  "usage": {
    "outputs_charged": 2,
    "remaining": 4998
  }
}
POST

/v1/video

New

Record a professional demo video of multi-step browser automation with cursor highlighting and click effects. Each video costs 3 API requests. Local URLs are not supported — Puppeteer runs on our servers, not yours. To record a local dev server, expose it first with ngrok http 3000 and use the public ngrok URL.

Perfect for product demos: Record polished browser walkthroughs with realistic cursor movements and click effects — no screen recording software needed. Ideal for docs, landing pages, onboarding flows, and changelogs.

Top-Level Parameters

ParameterTypeDefaultDescription
stepsarrayRequired. Array of step objects (same actions as sequence, except no screenshot/pdf)
viewportobject{width, height} — default 1280×720
formatstringmp4mp4, webm, or gif
frameratenumber30Frames per second: 24, 30, or 60
darkModebooleanfalseEmulate dark color scheme
blockBannersbooleantrueAuto-hide cookie consent banners
deviceScaleFactornumber1Pixel ratio 1–3 (use 2 for retina)
pacenumber | string1.0Controls video speed. Number 0.256.0 (higher = slower/more deliberate) or preset: "fast" (0.5×), "normal" (1×), "slow" (2×), "dramatic" (3×), "cinematic" (4.5×). Scales cursor movement, pauses between steps, typing speed, and all cosmetic delays.
response_typestringbinarySet to "json" for base64-encoded response with metadata

Cursor Options

ParameterTypeDefaultDescription
cursor.visiblebooleantrueShow animated cursor in the recording
cursor.stylestringhighlighthighlight, circle, spotlight, dot, or classic NEW
cursor.colorstring#3B82F6Cursor color (hex)
cursor.sizenumber20Cursor size in pixels (8–60)
cursor.smoothingbooleantrueSmooth cursor movement between actions
cursor.opacitynumber1.0Cursor opacity (0.1–1.0)
cursor.persistbooleanfalseKeep cursor visible between actions instead of fading out NEW

Zoom Options

ParameterTypeDefaultDescription
Per-step zoom — Add a zoom object to individual click/dblclick steps to zoom into that specific action.
{ "action": "click", "selector": "#btn", "zoom": { "enabled": true, "level": 1.5 } }

Click Effect Options

ParameterTypeDefaultDescription
clickEffect.enabledbooleantrueShow visual feedback on clicks
clickEffect.stylestringrippleripple, pulse, or ring
clickEffect.colorstringcursor colorClick effect color (hex) — defaults to cursor.color

Frame Options NEW

ParameterTypeDefaultDescription
frame.enabledbooleanfalseAdd browser window frame chrome overlay
frame.stylestringmacosmacos, windows, or minimal
frame.themestringautolight, dark, or auto (matches darkMode)
frame.showUrlbooleantrueShow the current URL in the frame’s address bar

Background Options NEW

ParameterTypeDefaultDescription
background.enabledbooleanfalseAdd a decorative background behind the browser viewport
background.typestringgradientgradient or solid
background.gradientstringoceanPreset: ocean, sunset, forest, midnight, aurora, or custom
background.colorstring#1e3a5fBackground color for solid type (hex)
background.colorsarrayArray of 2 hex colors for custom gradient
background.paddingnumber40Padding around viewport in pixels (0–120)
background.borderRadiusnumber12Border radius of viewport in pixels (0–40)

Audio Guide Options NEW

Add AI-generated narration to your demo videos. Two modes are available:

Per-step mode (default) — Add narration text to individual steps. Each clip is spoken before the action executes.

Script mode — Provide a single audioGuide.script with {{N}} step markers for continuous narration. Steps execute when the narration reaches each marker, creating a natural flow. Example: "Welcome to our app. {{1}} Here are the features. {{2}} Click to get started."

ParameterTypeDefaultDescription
audioGuide.enabledbooleanfalseEnable Audio Guide narration
audioGuide.providerstringazureTTS provider: azure or openai
audioGuide.voicestringavaVoice preset name (see list below)
audioGuide.speednumber1.0Speech rate (0.5–2.0)
audioGuide.pitchstringdefaultVoice pitch (Azure only)
audioGuide.volumestringdefaultAudio volume (Azure only)
audioGuide.stylestringSpeaking style (Azure only): narration-professional, cheerful, etc.
audioGuide.styleDegreenumber1.0Style intensity (Azure only, 0.01–2.0)
audioGuide.modelstringtts-1OpenAI model (OpenAI only)
audioGuide.scriptstringScript mode narration. A single text with {{N}} step markers (0-indexed). When provided, per-step narration fields are ignored. Max 5000 chars.

Available Voices

ProviderVoiceGender
AzureavaFemale
andrewMale
emmaFemale
brianMale
ariaFemale
guyMale
jennyFemale
davisMale
christopherMale
michelleFemale
OpenAIalloyNeutral
echoMale
fableNeutral
novaFemale
onyxMale
shimmerFemale

Available Actions

ActionRequired FieldsDescription
navigateurlGo to a URL (http/https only)
clickselectorClick an element by CSS selector
dblclickselectorDouble-click an element by CSS selector
fillselector, valueClear and type into an input field
selectselector, valueSelect a dropdown option by value
hoverselectorHover over an element (reveals tooltips, dropdowns)
scrollselector or x, yScroll to element or absolute position
waitmsWait fixed milliseconds (max 10000). Add live: true to capture animated content.
wait_forselectorWait for element to appear and become visible (optional timeout, max 15s)
evaluatescriptRun JavaScript in page context (max 5000 chars, max 2 per sequence)

Step Notes and Narration NEW

Add a note string to any step to display a text overlay in the video — perfect for guided product tours, onboarding walkthroughs, and tutorial videos. The note appears as a styled callout near the target element before the action executes. Use narration with audioGuide.enabled for spoken voice-over on each step.

ParameterTypeMax LengthDescription
notestring500 charsOptional. Text overlay displayed before the action executes. Available on navigate, click, dblclick, fill, hover, and scroll actions.
narrationstring500 charsOptional. TTS narration spoken before the action when audioGuide.enabled is true. Available on same actions as note.
Auto-scroll to viewport: If a click, fill, or hover target is outside the visible viewport, the video engine automatically scrolls the element into view before the cursor moves to it — so note overlays, cursor movement, and click effects are always visible in the recording.

Plan Limits

PlanBase + Per-Step BudgetMax StepsFormats
Free20s + 5s/step10mp4
Starter30s + 5s/step20mp4, webm
Growth45s + 6s/step30mp4, webm, gif
Scale60s + 6s/step50mp4, webm, gif
Duration scales with steps and pace: The timeout is base + (steps × per-step budget × pace). Using pace: "slow", pace: "dramatic", or pace: "cinematic" automatically extends the allowed recording time so your video doesn't time out.
Cost: Each video recording costs 3 API requests against your monthly quota. Max 2 evaluate steps per video.

Example: Record a guided demo video

cURL
curl -X POST https://pagebolt.dev/api/v1/video \
  -H "x-api-key: pf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      { "action": "navigate", "url": "https://pagebolt.dev" },
      { "action": "scroll", "selector": "#pricing" },
      { "action": "wait", "ms": 3000 },
      { "action": "click", "selector": "#get-started",
        "note": "Click here to sign up for PageBolt" }
    ],
    "viewport": { "width": 1280, "height": 800 },
    "format": "mp4",
    "blockBanners": true,
    "pace": "normal",
    "cursor": { "style": "highlight", "color": "#3B82F6", "persist": true },
    "clickEffect": { "enabled": true, "style": "ripple" },
    "frame": { "enabled": true, "style": "macos", "showUrl": true },
    "background": {
      "enabled": true, "type": "gradient", "padding": 120,
      "borderRadius": 12, "gradient": "sunset"
    }
  }' \
  -o demo.mp4

Example: Record a demo video with Audio Guide

cURL
curl -X POST https://pagebolt.dev/api/v1/video \
  -H "x-api-key: pf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      { "action": "navigate", "url": "https://pagebolt.dev",
        "narration": "Welcome to PageBolt, the screenshot and automation API." },
      { "action": "scroll", "selector": "#pricing",
        "narration": "Let me show you our pricing plans." },
      { "action": "click", "selector": "#get-started",
        "note": "Click here to sign up",
        "narration": "Click Get Started to create your free account." }
    ],
    "viewport": { "width": 1280, "height": 800 },
    "format": "mp4",
    "blockBanners": true,
    "pace": "normal",
    "audioGuide": {
      "enabled": true,
      "provider": "azure",
      "voice": "ava",
      "speed": 1.0
    }
  }' \
  -o demo-with-narration.mp4

Example: Script Mode — continuous narration with step markers

cURL
curl -X POST https://pagebolt.dev/api/v1/video \
  -H "x-api-key: pf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      { "action": "navigate", "url": "https://pagebolt.dev" },
      { "action": "scroll", "selector": "#features" },
      { "action": "click", "selector": "#tab-python" },
      { "action": "scroll", "selector": "#pricing" },
      { "action": "click", "selector": "#get-started" }
    ],
    "viewport": { "width": 1280, "height": 800 },
    "format": "mp4",
    "blockBanners": true,
    "audioGuide": {
      "enabled": true,
      "provider": "azure",
      "voice": "ava",
      "script": "Welcome to PageBolt — the web capture API. {{1}} Here are the core features — screenshots, PDFs, video recording, and more. {{2}} And it works in any language — here is the Python example. {{3}} Pricing is simple and transparent — start free. {{4}} Click here to get your free API key."
    }
  }' \
  -o demo-script-mode.mp4

In script mode, the narration is synthesized as a single continuous audio track. Step markers {{N}} (0-indexed) tell the video engine when to execute each step, synchronized to the narration timing. Steps not referenced by a marker still execute at their natural position.

JSON Response (when response_type=json)

JSON
{
  "data": "base64...",
  "format": "mp4",
  "content_type": "video/mp4",
  "size_bytes": 2457600,
  "duration_ms": 12400,
  "frames": 372,
  "steps_completed": 5,
  "total_steps": 5,
  "step_results": [
    {"step_index": 0, "action": "navigate", "status": "ok", "duration_ms": 2341},
    {"step_index": 1, "action": "click", "status": "ok", "duration_ms": 512},
    {"step_index": 2, "action": "fill", "status": "ok", "duration_ms": 1087},
    {"step_index": 3, "action": "click", "status": "ok", "duration_ms": 445},
    {"step_index": 4, "action": "wait", "status": "ok", "duration_ms": 2000}
  ],
  "usage": {
    "video_cost": 3,
    "remaining": 4847
  }
}
Default response: Binary video data with the appropriate Content-Type header (video/mp4, video/webm, or image/gif). Status 200 on success.
POST

/v1/inspect

New

Inspect a web page and get a structured map of all interactive elements, headings, forms, links, and images — each with a unique CSS selector ready for use with /v1/sequence. Returns compact JSON optimized for AI agents.

Built for AI agents: Use this endpoint before calling /v1/sequence to discover what elements exist on a page and get reliable CSS selectors. Returns text (2-15 KB) instead of an image, saving tokens and improving accuracy.

Parameters

ParameterTypeDefaultDescription
urlstringRequired (if no html). URL to inspect.
htmlstringRaw HTML to inspect (alternative to url).
widthinteger1280Viewport width in pixels (1–3840).
heightinteger720Viewport height in pixels (1–2160).
viewportDevicestringDevice preset (e.g. "iphone_14_pro"). See /devices.
darkModebooleanfalseEmulate dark color scheme.
waitUntilstringnetworkidle2load, domcontentloaded, networkidle0, networkidle2.
waitForSelectorstringWait for this CSS selector before inspecting.
cookiesarrayArray of "name=value" strings or {name, value, domain?} objects.
headersobjectExtra HTTP headers.
authorizationstringAuthorization header value.
authStateobjectFull browser auth state (cookies + localStorage). See Authenticated Recording.
userAgentstringOverride the browser User-Agent.
blockBannersbooleanfalseHide cookie consent banners.
blockAdsbooleanfalseBlock advertisements.
blockChatsbooleanfalseBlock live chat widgets.
blockTrackersbooleanfalseBlock tracking scripts.
bypassCSPbooleanfalseBypass Content-Security-Policy.
hideSelectorsarrayCSS selectors to hide before inspecting.
injectCssstringCustom CSS to inject.
injectJsstringCustom JavaScript to execute before inspecting.

Response

Always returns JSON with the following structure:

{
  "url": "https://example.com",
  "title": "Example Page",
  "metadata": {
    "description": "Page description",
    "ogTitle": "OG Title",
    "lang": "en",
    "httpStatusCode": 200
  },
  "elements": [
    {
      "tag": "button",
      "role": "button",
      "text": "Sign Up",
      "selector": "#signup-btn",
      "attributes": { "id": "signup-btn", "type": "submit" },
      "rect": { "x": 120, "y": 340, "width": 160, "height": 40 }
    },
    {
      "tag": "input",
      "role": "input",
      "text": "",
      "selector": "input[name='email']",
      "attributes": { "type": "email", "name": "email", "placeholder": "Enter email" },
      "rect": { "x": 20, "y": 280, "width": 300, "height": 36 }
    }
  ],
  "headings": [
    { "level": 1, "text": "Welcome", "selector": "h1" }
  ],
  "forms": [
    { "selector": "form#signup", "action": "/signup", "method": "POST",
      "fields": ["input[name='email']", "input[name='password']"] }
  ],
  "links": [
    { "text": "About", "href": "/about", "selector": "nav a[href='/about']" }
  ],
  "images": [
    { "alt": "Logo", "src": "/logo.png", "selector": "img[alt='Logo']",
      "rect": { "x": 10, "y": 10, "width": 120, "height": 40 } }
  ],
  "duration_ms": 1234
}

cURL Example

curl -X POST https://pagebolt.dev/api/v1/inspect \
  -H "x-api-key: pf_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "blockBanners": true
  }'
Usage: Costs 1 API request. Available on all plans. Combine with /v1/sequence for reliable browser automation — inspect first, then interact using the returned selectors.

Persistent Browser Sessions NEW

Sessions let you keep a browser page alive across multiple API calls. Cookies, localStorage, and authentication state persist between requests — useful for multi-step agent workflows that need to log in once and then interact with authenticated pages repeatedly.

Plan requirement: Sessions are available on Starter, Growth, and Scale plans only. Free tier returns 403.

Important: Sessions are in-memory only. They do not survive server restarts. Build your workflows to handle a missing session gracefully (catch the 404 and re-authenticate).

Limits

LimitValueNotes
Max concurrent sessions (global)3Shared across all users. Returns 503 if full.
Max sessions per API key2Returns 429 if exceeded.
Inactivity timeout10 minutesResets on each request that uses the session.
Hard cap30 minutesAbsolute maximum regardless of activity.

Example: Log in once, screenshot multiple pages

# 1. Create a session
SESSION=$(curl -s -X POST https://pagebolt.dev/api/v1/sessions \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' | jq -r .session_id)

# 2. Log in (auth cookies are now stored in the session)
curl -s -X POST https://pagebolt.dev/api/v1/sequence \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"session_id\": \"$SESSION\",
    \"steps\": [
      {\"action\": \"navigate\", \"url\": \"https://app.example.com/login\"},
      {\"action\": \"fill\", \"selector\": \"#email\", \"value\": \"user@example.com\"},
      {\"action\": \"fill\", \"selector\": \"#password\", \"value\": \"hunter2\"},
      {\"action\": \"click\", \"selector\": \"button[type=submit]\"},
      {\"action\": \"screenshot\", \"name\": \"logged-in\"}
    ]
  }" > /dev/null

# 3. Take screenshots of authenticated pages (session still alive)
curl -X POST https://pagebolt.dev/api/v1/screenshot \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"session_id\": \"$SESSION\", \"url\": \"https://app.example.com/dashboard\"}" \
  -o dashboard.png

# 4. Clean up when done
curl -X DELETE https://pagebolt.dev/api/v1/sessions/$SESSION \
  -H "x-api-key: YOUR_API_KEY"
POST

/v1/sessions

New

Create a new persistent browser session. Returns a session_id you can pass to /screenshot and /sequence requests.

Request body

ParameterTypeDefaultDescription
cookiesarrayOptional. Array of cookie objects to pre-set on the session page before any navigation.
viewportobject1280×720Optional. { "width": 1280, "height": 720 }
stealthbooleanfalseOptional. Use puppeteer-extra stealth plugin for this session. Stealth sessions get their own isolated browser instance.

Response

{
  "session_id": "sess_a1b2c3d4e5f6g7h8i9j0k1l2",
  "expires_at": "2026-02-23T10:30:00.000Z",
  "expires_in_seconds": 600,
  "note": "Sessions expire after 10 minutes of inactivity. They do not persist across server restarts."
}
GET

/v1/sessions

List all active sessions owned by the current API key, with idle time and remaining TTL for each.

Response

{
  "sessions": [
    {
      "session_id": "sess_a1b2c3d4e5f6g7h8i9j0k1l2",
      "created_at": "2026-02-23T10:20:00.000Z",
      "expires_at": "2026-02-23T10:32:15.000Z",
      "idle_seconds": 45,
      "expires_in_seconds": 555
    }
  ],
  "count": 1
}
DELETE

/v1/sessions/:id

Destroy a session immediately, releasing the browser page. Returns 204 No Content on success, or 404 if the session has already expired or belongs to a different key.

Always destroy sessions when your workflow is complete rather than waiting for the inactivity timeout to free the slot.

GET

/v1/usage

Check your current usage and plan limits programmatically. No parameters needed.

cURL
curl https://pagebolt.dev/api/v1/usage \
  -H "x-api-key: pf_live_your_key"

Response

JSON
{
  "plan": "starter",
  "usage": {
    "current": 1247,
    "limit": 5000,
    "remaining": 3753
  }
}
GET

/v1/devices

New

Returns the list of available device presets for the viewportDevice parameter. No parameters needed.

cURL
curl https://pagebolt.dev/api/v1/devices \
  -H "x-api-key: pf_live_your_key"

Response (excerpt)

JSON
{
  "devices": [
    {"id": "iphone_se",              "name": "iPhone SE",              "width": 375,  "height": 667,  "deviceScaleFactor": 2,     "mobile": true},
    {"id": "iphone_14_pro",          "name": "iPhone 14 Pro",          "width": 393,  "height": 852,  "deviceScaleFactor": 3,     "mobile": true},
    {"id": "iphone_15_pro_max",      "name": "iPhone 15 Pro Max",      "width": 430,  "height": 932,  "deviceScaleFactor": 3,     "mobile": true},
    {"id": "ipad_pro_12",            "name": "iPad Pro 12.9\"",        "width": 1024, "height": 1366, "deviceScaleFactor": 2,     "mobile": true},
    {"id": "pixel_8_pro",            "name": "Google Pixel 8 Pro",     "width": 412,  "height": 915,  "deviceScaleFactor": 3.5,   "mobile": true},
    {"id": "galaxy_s24_ultra",       "name": "Galaxy S24 Ultra",       "width": 412,  "height": 915,  "deviceScaleFactor": 3.5,   "mobile": true},
    {"id": "macbook_pro_14",         "name": "MacBook Pro 14\"",       "width": 1512, "height": 982,  "deviceScaleFactor": 2,     "mobile": false},
    {"id": "desktop_4k",             "name": "Desktop 4K",             "width": 3840, "height": 2160, "deviceScaleFactor": 1,     "mobile": false}
  ]
}
25+ presets available including iPhones (SE through 15 Pro Max), iPads, Pixel, Galaxy, MacBooks, and desktop resolutions. Use the id value as the viewportDevice parameter.

MCP Server (AI Agent Integration)

PageBolt includes a built-in Model Context Protocol (MCP) server that lets AI coding assistants call the PageBolt API directly. Say "take a screenshot of example.com" in your IDE and get the result inline.

Supported clients: Claude Desktop, Cursor, Windsurf, Cline, and any MCP-compatible agent.

Available Tools

ToolDescription
take_screenshotCapture a screenshot of a URL, HTML, or Markdown. Returns an inline image. Supports all 50+ screenshot parameters.
generate_pdfGenerate a PDF from a URL or HTML. Saves to disk and returns the file path.
create_og_imageCreate an OG/social card image from templates or custom HTML. Returns an inline image.
run_sequenceExecute a multi-step browser automation sequence with multiple outputs.
record_videoRecord a demo video of browser automation with cursor effects, click highlighting, step notes, and Audio Guide narration. Saves to disk. Costs 3 requests. NEW
inspect_pageInspect a page and get a structured map of interactive elements with CSS selectors. Use before run_sequence.
list_devicesList all available device presets for viewport emulation.
check_usageCheck your current API usage and plan limits.

Environment Variables

VariableRequiredDefaultDescription
PAGEBOLT_API_KEYYesYour PageBolt API key (from the Dashboard)
PAGEBOLT_BASE_URLNohttps://pagebolt.devPageBolt API URL. Override for self-hosted instances.

Example 11: Claude Desktop / Cursor config

Add this to your Claude Desktop config (~/.claude/claude_desktop_config.json) or Cursor MCP config (.cursor/mcp.json):

claude_desktop_config.json / .cursor/mcp.json
{
  "mcpServers": {
    "pagebolt": {
      "command": "npx",
      "args": ["-y", "pagebolt-mcp"],
      "env": {
        "PAGEBOLT_API_KEY": "pf_live_your_key_here"
      }
    }
  }
}

Example Prompts

Once configured, you can ask your AI agent things like:

"Take a screenshot of https://my-saas.com in dark mode at 1920x1080"
"Generate a PDF of this invoice HTML and save it to ./invoices/jan-2026.pdf"
"Create an OG image with the title 'How to Build a SaaS' using the gradient template"
"List all available device presets"
"Run a sequence: navigate to example.com, click the pricing link, and screenshot both pages"
"Record a demo video of navigating to example.com and clicking the sign-up button, with a slow pace and step notes"
"How many API requests do I have left this month?"
Note: All MCP tool calls use your API key and count against your plan's usage quota — same as any direct API request.

CI / CD Integration

NEW

Automatically generate polished demo videos from pull requests. An AI agent reads your PR diff, inspects the deployed preview, and records a video showing the feature in action — then posts it as a PR comment. No config files or scripts required.

How it works: Open a PR → the GitHub Action triggers → the AI agent inspects your preview deployment → a polished demo video is recorded and posted to the PR. Reviewers see the feature in action before reviewing code.

Requirements

RequirementDetails
PageBolt API keyGet one free at pagebolt.dev/dashboard
AI provider API keyAnthropic (Claude) or OpenAI (GPT-4o). The agent uses tool-calling to inspect and record.
Preview deploymentA publicly accessible URL for the PR (e.g. Vercel preview, Netlify deploy preview, or any staging URL).

GitHub Action

The simplest way to add demo videos to your PRs. Add this workflow file to your repository:

Basic Setup (Vercel)

.github/workflows/pagebolt-demo.yml
name: PageBolt Demo Video
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  demo-video:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Wait for Vercel preview
        uses: patrickedqvist/wait-for-vercel-preview@v1.3.2
        id: preview
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          max_timeout: 300

      - name: Record demo video
        uses: Custodia-Admin/pagebolt/ci/action@main
        with:
          api-key: ${{ secrets.PAGEBOLT_API_KEY }}
          ai-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          preview-url: ${{ steps.preview.outputs.url }}

Action Inputs

InputRequiredDefaultDescription
api-keyYesYour PageBolt API key
ai-api-keyYesAnthropic or OpenAI API key for the AI agent
preview-urlYesPreview deployment URL for this PR
ai-providerNoanthropicAI provider: anthropic or openai
ai-modelNoautoOverride the AI model (e.g. claude-sonnet-4-20250514)
spec-dirNo.pagebolt/demosPath to YAML demo spec files (optional, for non-agent mode)
output-dirNo./pagebolt-artifactsDirectory to save video artifacts
github-tokenNogithub.tokenGitHub token for posting PR comments
verboseNofalseEnable verbose logging

Action Outputs

OutputDescription
results-jsonJSON string of all recording results
artifact-dirPath to directory containing video artifacts
videos-recordedNumber of videos successfully recorded

Netlify Example

.github/workflows/pagebolt-demo.yml
name: PageBolt Demo Video
on:
  deployment_status:

jobs:
  demo-video:
    if: github.event.deployment_status.state == 'success'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Record demo video
        uses: Custodia-Admin/pagebolt/ci/action@main
        with:
          api-key: ${{ secrets.PAGEBOLT_API_KEY }}
          ai-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          preview-url: ${{ github.event.deployment_status.target_url }}

CLI Reference

Use pagebolt-ci directly for local testing or non-GitHub CI systems.

Installation

bash
npm install -g pagebolt-ci

# Or use npx without installing:
npx pagebolt-ci run --api-key pf_live_... --preview-url https://preview.example.com

Commands

pagebolt-ci run

Record demo videos. Automatically chooses between spec-based mode (if .pagebolt/demos/*.yml files exist) and autonomous agent mode.

FlagDescription
--api-keyPageBolt API key (or set PAGEBOLT_API_KEY)
--preview-urlURL of the preview deployment to record
--ai-provideranthropic or openai
--ai-api-keyAPI key for the AI provider
--ai-modelOverride AI model (e.g. claude-sonnet-4-20250514)
--pr-titlePR title (passed to the agent for context)
--pr-descriptionPR description / body (helps the agent understand the feature)
--output-dirDirectory for video output (default: ./pagebolt-artifacts)
--base-urlPageBolt API base URL (default: https://pagebolt.dev)
--verboseEnable verbose logging

Example: Agent Mode

bash
pagebolt-ci run \
  --api-key pf_live_your_key \
  --ai-provider anthropic \
  --ai-api-key sk-ant-your_key \
  --preview-url https://preview-abc123.vercel.app \
  --pr-title "feat: Add user onboarding flow" \
  --output-dir ./demo-videos \
  --verbose

pagebolt-ci comment

Post or update a PR comment with recording results. Usually called automatically by the GitHub Action after run completes.

FlagDescription
--github-tokenGitHub token with PR comment permissions
--repoRepository in owner/repo format
--pr-numberPR number to comment on
--results-filePath to _results.json from the run command

Agent Mode (Zero-Config)

When no spec files are found in .pagebolt/demos/, the CLI automatically enters Agent Mode. An AI agent (Claude or GPT-4o) autonomously:

  1. Reads the PR title, description, and diff to understand the feature
  2. Calls inspect_page on the preview URL to discover interactive elements
  3. Plans a demo flow — which buttons to click, which inputs to fill, what sequence tells the best story
  4. Calls record_video with the planned steps, producing a polished MP4
Agent capabilities: The agent has access to two PageBolt tools: inspect_page (discover page elements) and record_video (record a demo). It uses up to 15 turns of reasoning to plan and execute the recording.

Video Settings

Agent-recorded videos automatically include polished defaults:

SettingDefault
CursorClassic pointer, always visible, smooth movement
FramemacOS dark window chrome
BackgroundGradient with 120px padding and 40px border radius
Click effectsRipple effect on every click
PaceNormal (1x)
Step notesTooltip annotations on every meaningful step
BlockingAds, banners, chat widgets, and trackers blocked

Supported AI Providers

ProviderRecommended ModelNotes
anthropicclaude-sonnet-4-20250514Best results. Excellent tool-calling and planning.
openaigpt-4oGood alternative. Supports function calling.

Spec-Based Mode (Optional)

For deterministic recordings (no AI), create YAML spec files in .pagebolt/demos/:

.pagebolt/demos/onboarding.yml
name: Onboarding Flow
description: Demo of the new user onboarding experience
triggers:
  paths:
    - src/components/onboarding/**
    - src/pages/welcome.*
viewport:
  width: 1280
  height: 720
steps:
  - action: navigate
    url: "{{preview_url}}/welcome"
    note: Opening the welcome page
  - action: wait
    ms: 1500
  - action: click
    selector: "#get-started-btn"
    note: Click Get Started
  - action: fill
    selector: "#company-name"
    value: Acme Corp
    note: Enter company name
  - action: click
    selector: "#continue-btn"
    note: Continue to next step

When spec files exist and match changed files in the PR, spec-based mode takes priority over agent mode. Use {{preview_url}} as a variable placeholder that resolves to the PR's preview deployment URL.

FAQ

Common questions about PageBolt's API behaviour.

Can I capture a local dev server (localhost)?

Not directly. Puppeteer runs on PageBolt's servers — not on your machine — so URLs like http://localhost:3000 or http://127.0.0.1:8080 resolve to our server's loopback, not yours. Private IP ranges are also blocked as an SSRF safeguard.

The fix is to expose your local server with a tunnel, then pass the public URL to PageBolt:

Terminal — expose local port 3000
# ngrok (most common)
ngrok http 3000
# → Forwarding: https://abc123.ngrok-free.app → localhost:3000

# Cloudflare Tunnel (no account required for quick tests)
cloudflared tunnel --url http://localhost:3000
# → https://random-name.trycloudflare.com

Then use the public tunnel URL in your API call:

JSON body
{
  "url": "https://abc123.ngrok-free.app",
  "fullPage": true
}

This works for all endpoints — /screenshot, /sequence, /video, and /pdf. ngrok's free tier is sufficient for development and CI use; Cloudflare Tunnel requires no account at all.

Questions? Email support@pagebolt.dev

© 2026 PageBolt. All rights reserved.