PageShot API

A powerful, developer-friendly API for capturing screenshots of any webpage. Built on Chromium for pixel-perfect accuracy, completely free with no API key required.

Base URL: https://pageshot.site/v1

Get Started

PageShot is completely free. No API key required. Just send a request with a URL and get your screenshot.

Quickstart

Take your first screenshot in under 30 seconds:

# Just pass a URL — no API key needed
curl "https://pageshot.site/v1/screenshot?url=https://example.com" \
  --output screenshot.png

# That's it! Open screenshot.png to see the result.

Authentication

PageShot is completely free and requires no authentication. Simply make a request to any endpoint.

GET /v1/screenshot

GET /v1/screenshot?url=https://example.com

Returns a screenshot image directly. Ideal for embedding in <img> tags or downloading.

Example Request

GET /v1/screenshot?url=https://example.com&width=1920&height=1080&format=png&dark_mode=true

Response Headers

HeaderDescription
X-Screenshot-TimeCapture duration (e.g., 2341ms)
X-Page-TitleURL-encoded page title from the captured page
X-Page-StatusHTTP status code of the target page (e.g., 200, 404)
X-Resolved-UrlFinal URL after any redirects
Content-Typeimage/png, image/jpeg, or image/webp

GET /v1/preview

GET /v1/preview?url=https://example.com

Optimized link preview thumbnail. Returns a small, fast JPEG image with smart defaults — perfect for link cards, newsletters, social embeds, and AI vision pipelines. Ads are blocked and cookie banners hidden automatically.

Parameters

ParameterTypeDefaultDescription
urlstringrequiredURL to capture
widthinteger300Output image width (100-800px). Height auto-scales.
dark_modebooleanfalseCapture in dark color scheme

Optimized Defaults

SettingValueWhy
Output formatJPEG (quality 60)~5x smaller files than PNG
Viewport1280×720Standard desktop capture
Output width300pxCard-sized thumbnail
Ads blockedYesClean preview image
Banners hiddenYesNo cookie consent popups
Timeout15 secondsFast fail for slow pages
Cache24 hoursPreviews don't need real-time freshness

Example

# Get a 300px-wide link preview thumbnail
curl "https://pageshot.site/v1/preview?url=https://example.com" \
  --output preview.jpg

# Wider preview for newsletter cards
curl "https://pageshot.site/v1/preview?url=https://example.com&width=600" \
  --output newsletter-card.jpg

# Embed directly in HTML
<img src="https://pageshot.site/v1/preview?url=https://example.com" alt="Preview" />

POST /v1/screenshot

POST /v1/screenshot

More flexible screenshot capture. Supports JSON body and optional JSON response with base64 image.

Request Body (JSON)

{
  "url": "https://example.com",
  "width": 1920,
  "height": 1080,
  "full_page": true,
  "format": "png",
  "dark_mode": true,
  "block_ads": true,
  "css": "header { display: none !important; }",
  "selector": ".main-content",
  "delay": 2000,
  "response": "json"
}

JSON Response (when response=json)

{
  "success": true,
  "data": {
    "url": "https://example.com",
    "pageStatus": 200,
    "image": "data:image/png;base64,iVBORw0KGgo...",
    "format": "png",
    "width": 1920,
    "height": 1080,
    "size": 245632,
    "captureTime": "2341ms"
  }
}

POST /v1/html

POST /v1/html

Render raw HTML/CSS to an image. Perfect for generating OG images, email previews, social cards, and dynamic content from templates. No URL needed — just send your HTML.

Request Body (JSON)

{
  "html": "<div style='padding:40px;background:#0a0a0f;color:#00f0ff;font-family:sans-serif'><h1>Hello World</h1><p>Generated with PageShot</p></div>",
  "width": 1200,
  "height": 630,
  "format": "png",
  "device_scale": 2,
  "response": "json"
}

Parameters

ParameterTypeRequiredDescription
htmlstringYesRaw HTML content to render (max 2MB)
widthintegerNoViewport width (default: 1280, range: 320-3840)
heightintegerNoViewport height (default: 720, range: 200-2160)
formatstringNoOutput format: png, jpeg, webp (default: png)
qualityintegerNoJPEG/WebP quality 1-100 (default: 80)
device_scalefloatNoDevice scale factor 0.5-3 (default: 1)
cssstringNoAdditional CSS to inject after rendering
selectorstringNoCapture a specific element from the HTML
full_pagebooleanNoCapture entire content height
dark_modebooleanNoForce dark color scheme
delayintegerNoWait before capture (ms, max 10000)
responsestringNoSet to "json" for base64 JSON response

Use Cases

  • OG Image generation — Render dynamic Open Graph images from HTML templates
  • Email previews — Generate thumbnail previews of HTML email templates
  • Social cards — Create custom social media cards with dynamic data
  • Certificates & badges — Generate personalized certificates or achievement badges
  • Invoice thumbnails — Preview invoice or document layouts before PDF export

Example: Generate an OG Image

curl -X POST "https://pageshot.site/v1/html" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<div style=\"width:1200px;height:630px;background:linear-gradient(135deg,#0a0a0f,#1a1a2e);display:flex;align-items:center;justify-content:center;color:#00f0ff;font-family:sans-serif\"><h1 style=\"font-size:72px\">My Blog Post Title</h1></div>",
    "width": 1200,
    "height": 630,
    "format": "png"
  }' \
  --output og-image.png

POST /v1/pdf

POST /v1/pdf

Convert any webpage to a PDF document. Powered by Chromium's print engine for pixel-perfect rendering. Perfect for archiving, reports, and documentation.

Request Body (JSON)

{
  "url": "https://example.com",
  "pdf_format": "A4",
  "landscape": false,
  "print_background": true,
  "pdf_scale": 1,
  "dark_mode": false,
  "block_ads": true,
  "css": "nav { display: none !important; }"
}

Parameters

ParameterTypeRequiredDescription
urlstringYesThe webpage URL to convert to PDF
pdf_formatstringNoPage size: A4, A3, A5, Letter, Legal, Tabloid (default: A4)
landscapebooleanNoLandscape orientation (default: false)
print_backgroundbooleanNoInclude background colors/images (default: true)
pdf_scalefloatNoScale of the content 0.1-2 (default: 1)
marginobjectNoPage margins: { top, right, bottom, left } (default: 0.5in each)
header_templatestringNoHTML template for page header
footer_templatestringNoHTML template for page footer
cssstringNoCustom CSS to inject before PDF generation
block_adsbooleanNoBlock ads and trackers (default: false)
dark_modebooleanNoForce dark color scheme (default: false)
delayintegerNoWait before capture (ms, max 10000)
wait_for_selectorstringNoWait for element before generating PDF

Response Headers

HeaderDescription
Content-Typeapplication/pdf
X-Render-TimeGeneration duration (e.g., 1523ms)
X-Page-TitleURL-encoded page title
X-Resolved-UrlFinal URL after redirects

Example: Save a webpage as PDF

curl -X POST "https://pageshot.site/v1/pdf" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "pdf_format": "A4", "print_background": true}' \
  --output page.pdf

POST /v1/html/pdf

POST /v1/html/pdf

Render raw HTML/CSS to a PDF document. Generate invoices, reports, certificates, and documentation from HTML templates without a URL.

Request Body (JSON)

{
  "html": "<h1>Invoice #1234</h1><table>...</table>",
  "pdf_format": "A4",
  "landscape": false,
  "print_background": true
}

Parameters

Same parameters as POST /v1/pdf, but replace url with html (max 2MB).

Use Cases

  • Invoice generation — Render HTML invoice templates to pixel-perfect PDFs
  • Reports & documents — Generate reports from dynamic data with custom styling
  • Certificates — Create personalized certificates and diplomas
  • Documentation — Convert styled HTML documentation to distributable PDFs

Example: Generate an invoice PDF

curl -X POST "https://pageshot.site/v1/html/pdf" \
  -H "Content-Type: application/json" \
  -d '{"html": "<h1>Invoice #1234</h1><p>Total: $99.00</p>", "pdf_format": "A4"}' \
  --output invoice.pdf

POST /v1/screenshot/batch

POST /v1/screenshot/batch

Capture screenshots of multiple URLs in a single request. Returns JSON with base64-encoded images for each URL. Maximum 5 URLs per batch.

Request Body (JSON)

{
  "urls": [
    "https://example.com",
    "https://example.org",
    {
      "url": "https://example.net",
      "width": 375,
      "height": 812,
      "dark_mode": true
    }
  ],
  "width": 1280,
  "height": 720,
  "format": "png"
}

Each entry in urls can be a plain URL string (uses global options) or an object with a url field and per-URL option overrides.

Response

{
  "success": true,
  "total": 3,
  "succeeded": 3,
  "failed": 0,
  "results": [
    {
      "url": "https://example.com",
      "success": true,
      "data": {
        "image": "data:image/png;base64,iVBORw0KGgo...",
        "format": "png",
        "width": 1280,
        "height": 720,
        "size": 245632,
        "captureTime": "2341ms"
      }
    }
  ]
}

Limits

LimitValue
Max URLs per batch5
Rate limit30 requests/min (shared with single screenshot)

GET /v1/presets

GET /v1/presets

Lists all available device and platform presets. Use a preset name in the preset parameter to auto-configure viewport, scale factor, and user agent.

Available Presets

PresetWidthHeightScaleUse Case
desktop192010801xStandard desktop monitor
laptop13667681xCommon laptop screen
tablet76810242xGeneric tablet
mobile3758123xGeneric smartphone
iphone_143908443xiPhone 14 with Safari UA
iphone_14_pro_max4309323xiPhone 14 Pro Max with Safari UA
pixel_74129152.6xGoogle Pixel 7 with Chrome UA
ipad82011802xiPad with Safari UA
og_image12006301xOpen Graph / social preview
twitter_card10245121xTwitter Card preview
linkedin_post12006271xLinkedIn post image

Example: Using a Preset

curl "https://pageshot.site/v1/screenshot?url=https://example.com&preset=og_image" \
  --output og-preview.png

You can override individual preset values. For example, preset=mobile&width=414 uses the mobile preset but overrides the width.

GET /v1/status

GET /v1/status

Check API operational status. No authentication required.

{
  "status": "operational",
  "service": "PageShot API",
  "version": "2.0.0",
  "uptime": 86400.123,
  "timestamp": "2026-02-12T12:00:00.000Z"
}

Parameters Reference

ParameterTypeDefaultDescription
urlstringrequiredThe webpage URL to capture
presetstringnullDevice/platform preset (see presets)
widthinteger1280Viewport width (320-3840). Overrides preset.
heightinteger720Viewport height (200-2160)
full_pagebooleanfalseCapture entire scrollable page
formatstringpngOutput: png, jpeg, webp
qualityinteger80JPEG/WebP quality (1-100)
dark_modebooleanfalseForce dark color scheme
block_adsbooleanfalseBlock ads and trackers (also dismisses banners)
hide_bannersbooleanfalseDismiss cookie banners, consent popups, GDPR overlays, and chat widgets before capture
delayinteger0Wait before capture (ms, max 10000)
device_scalefloat1Device scale factor (0.5-3)
selectorstringnullCSS selector for element capture
wait_for_selectorstringnullWait for this CSS selector to be visible before capture
cssstringnullCustom CSS to inject
user_agentstringnullCustom User-Agent string
timeoutinteger30000Page load timeout (ms, 5000-60000)
resize_widthintegernullResize output image to this width in px (16-3840). Maintains aspect ratio.
resize_heightintegernullResize output image to this height in px (16-2160). Maintains aspect ratio.
headersobjectnullCustom HTTP headers to send (e.g., {"Authorization": "Bearer token"}). Max 20 headers. POST only.
cookiesarraynullCookies to set before capture. Array of {"name", "value"} objects (max 50). Scoped to target domain. POST only.
evaluatestringnullJavaScript code to execute on the page before capture (max 10KB). Runs in the browser context. Use to dismiss modals, click buttons, or set UI state.
clip_xintegernullRegion capture: X coordinate (0-15000). Requires clip_y, clip_width, clip_height.
clip_yintegernullRegion capture: Y coordinate (0-15000)
clip_widthintegernullRegion capture: width in pixels (1-15000)
clip_heightintegernullRegion capture: height in pixels (1-15000)
timezonestringnullIANA timezone ID for the browser context (e.g., America/New_York, Europe/Berlin, Asia/Tokyo). Affects Date, Intl, and locale-aware rendering.
localestringnullBCP 47 locale tag for the browser context (e.g., en-US, de-DE, ja-JP). Affects number/date formatting and navigator.language.
disable_javascriptbooleanfalseDisable JavaScript execution on the page. Captures static HTML only. Useful for security research, avoiding JS-driven redirects, or capturing pages without fingerprinting scripts.
latitudefloatnullGeolocation emulation: latitude (-90 to 90). Must be used together with longitude.
longitudefloatnullGeolocation emulation: longitude (-180 to 180). Must be used together with latitude. Triggers geo-targeted content rendering.
wait_untilstringdomcontentloadedPage load strategy: commit (fastest — response received), domcontentloaded (DOM parsed), load (all resources loaded), networkidle (no network activity for 500ms — best for SPAs and lazy-loaded content).
ignore_https_errorsbooleanfalseIgnore HTTPS/TLS certificate errors. Useful for capturing dev/staging environments with self-signed certificates.
responsestringbinarySet to json for base64 response

Code Examples

Node.js / JavaScript

// Using fetch (Node 18+) — no API key needed
const response = await fetch('https://pageshot.site/v1/screenshot', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://example.com',
    width: 1280,
    height: 720,
    format: 'png'
  })
});

const buffer = Buffer.from(await response.arrayBuffer());
require('fs').writeFileSync('screenshot.png', buffer);
console.log(`Captured in ${response.headers.get('X-Screenshot-Time')}`);

Pre-Capture JavaScript (evaluate)

// Dismiss a modal and scroll before capturing
const response = await fetch('https://pageshot.site/v1/screenshot', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://example.com',
    evaluate: 'document.querySelector(".modal-close")?.click(); window.scrollTo(0, 500);',
    width: 1280,
    height: 720
  })
});

Authenticated Screenshot (with cookies & headers)

// Capture a page behind authentication
const response = await fetch('https://pageshot.site/v1/screenshot', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://app.example.com/dashboard',
    headers: { 'Authorization': 'Bearer eyJhbGci...' },
    cookies: [
      { name: 'session_id', value: 'abc123' },
      { name: 'csrf_token', value: 'xyz789' }
    ],
    width: 1920,
    height: 1080
  })
});

Python

import requests

# No API key needed — just send the request
response = requests.post(
    'https://pageshot.site/v1/screenshot',
    json={
        'url': 'https://example.com',
        'width': 1280,
        'height': 720,
        'full_page': True,
        'format': 'png'
    }
)

with open('screenshot.png', 'wb') as f:
    f.write(response.content)

print(f"Captured in {response.headers['X-Screenshot-Time']}")

C# / .NET

// No API key needed
using var client = new HttpClient();

var payload = new {
    url = "https://example.com",
    width = 1920,
    height = 1080,
    full_page = true,
    dark_mode = true
};

var response = await client.PostAsJsonAsync(
    "https://pageshot.site/v1/screenshot", payload);

var bytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("screenshot.png", bytes);

PHP

// No API key needed
$ch = curl_init('https://pageshot.site/v1/screenshot');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'url' => 'https://example.com',
        'width' => 1920,
        'height' => 1080,
        'format' => 'png'
    ])
]);

$image = curl_exec($ch);
curl_close($ch);
file_put_contents('screenshot.png', $image);

Go

// No API key needed
payload := map[string]any{
    "url":    "https://example.com",
    "width":  1920,
    "height": 1080,
    "format": "png",
}

body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://pageshot.site/v1/screenshot",
    bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

data, _ := io.ReadAll(resp.Body)
os.WriteFile("screenshot.png", data, 0644)

Error Handling

All errors return JSON with an error field and descriptive message.

StatusCodeDescription
400INVALID_JSONMalformed JSON request body
400SELECTOR_NOT_FOUNDCSS selector not found on page
408WAIT_FOR_SELECTOR_TIMEOUTwait_for_selector element did not appear in time
400PAGE_TOO_TALLFull-page exceeds 15,000px height
400EVALUATE_FAILEDJavaScript evaluation failed (syntax error or runtime exception)
413PAYLOAD_TOO_LARGERequest body exceeds 1MB
429Rate limit exceeded30 requests per minute per IP
502NETWORK_ERRORTarget URL unreachable
503CONCURRENT_LIMITToo many simultaneous captures (max 5)
504TIMEOUTPage load exceeded timeout
500CAPTURE_FAILEDGeneric screenshot failure
500CONVERSION_FAILEDImage format conversion error

Example Error Response

{
  "error": "NETWORK_ERROR",
  "message": "Could not reach the target URL. Verify the URL is accessible.",
  "url": "https://invalid-domain.example",
  "docs": "/docs#errors"
}

Rate Limits

LimitValueScope
API requests30 / minutePer IP address
Concurrent renders5Per IP address
Page load timeout30 secondsPer request
Max viewport3840 x 2160Per request

Rate limit info is returned in response headers:

X-RateLimit-Limit: 30
X-RateLimit-Remaining: 28
X-RateLimit-Reset: 1707696000

MCP Integration

PageShot ships with a built-in Model Context Protocol (MCP) server. Connect PageShot directly to Claude, VS Code, Cursor, or any MCP-compatible AI client to take screenshots from your assistant.

Installation

Add the following to your MCP client configuration:

{
  "mcpServers": {
    "pageshot": {
      "command": "npx",
      "args": ["-y", "pageshot-api"]
    }
  }
}

Available Tools

ToolDescriptionParameters
take_screenshot Capture a screenshot of any webpage url (required), preset, width, height, format, quality, full_page, dark_mode, delay, selector, wait_for_selector, hide_banners, resize_width, resize_height, headers, cookies, evaluate, clip_x/clip_y/clip_width/clip_height

Environment Variables

VariableDefaultDescription
PAGESHOT_BASE_URL https://pageshot.site Override the base URL for API requests (e.g., for self-hosted instances)

Terms of Service

By using the PageShot API, you agree to the following terms:

  • The API is provided "as is" without warranty of any kind, express or implied.
  • You may use the API for lawful purposes only. Capturing screenshots of illegal content, phishing pages, or content you do not have rights to view is prohibited.
  • We reserve the right to rate-limit or block access to any IP address that abuses the service.
  • You may not use the API to systematically scrape or archive websites without the site owner's consent.
  • We are not liable for any damages arising from the use of this service.
  • These terms may be updated at any time. Continued use constitutes acceptance of updated terms.

Privacy Policy

PageShot is designed with privacy in mind:

  • No accounts or personal data: We do not require signup, email, or any personal information to use the API.
  • No screenshot storage: Screenshots are generated on-the-fly and streamed directly to you. We do not store, cache, or log captured images.
  • Minimal logging: We log request metadata (IP address, timestamp, requested URL) for rate limiting and abuse prevention only. Logs are retained for a maximum of 30 days.
  • No cookies or tracking: The API does not set cookies or use any tracking technologies.
  • No third-party sharing: We do not sell, share, or transfer any data to third parties.
  • Contact: For privacy-related inquiries, email damian.pozimski@gmail.com.

Support

Need help? Here's how to reach us: