URL to PDF

Capture any webpage as a PDF document.

URL to PDF

Capture any publicly accessible webpage as a PDF document. Supports dynamic content, custom viewports, and authentication.

POST /v1/pdf/url

Request Body

ParameterTypeRequiredDescription
urlstringYesURL to capture (must be publicly accessible)
optionsobjectNoPDF generation options

Options Object

ParameterTypeDefaultDescription
formatstring"A4"Paper format
landscapebooleanfalseLandscape orientation
marginobject-Page margins
print_backgroundbooleantrueInclude backgrounds
wait_fornumber0Wait time in ms for dynamic content
viewportobject-Browser viewport size
full_pagebooleanfalseCapture full scrollable page
cookiesarray-Cookies for authentication

Viewport Object

ParameterTypeDefaultDescription
widthnumber1920Viewport width in pixels
heightnumber1080Viewport height in pixels

Code Examples

curl -X POST https://api.pdfapi.dev/v1/pdf/url \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/report",
    "options": {
      "format": "A4",
      "wait_for": 2000,
      "viewport": {
        "width": 1920,
        "height": 1080
      }
    }
  }' \
  --output report.pdf
const response = await fetch('https://api.pdfapi.dev/v1/pdf/url', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.PDFAPI_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com/report',
    options: {
      format: 'A4',
      wait_for: 2000,
      full_page: true,
      viewport: { width: 1920, height: 1080 }
    }
  }),
});

if (!response.ok) {
  const error = await response.json();
  throw new Error(error.error.message);
}

const buffer = await response.arrayBuffer();
// Save or process the PDF
import requests
import os

response = requests.post(
    'https://api.pdfapi.dev/v1/pdf/url',
    headers={
        'Authorization': f'Bearer {os.environ["PDFAPI_KEY"]}',
        'Content-Type': 'application/json',
    },
    json={
        'url': 'https://example.com/report',
        'options': {
            'format': 'A4',
            'wait_for': 2000,
            'full_page': True,
            'viewport': {'width': 1920, 'height': 1080}
        }
    }
)

if response.status_code == 200:
    with open('report.pdf', 'wb') as f:
        f.write(response.content)
else:
    print(f"Error: {response.json()['error']['message']}")
package main

import (
    "bytes"
    "encoding/json"
    "io"
    "net/http"
    "os"
)

func main() {
    payload := map[string]interface{}{
        "url": "https://example.com/report",
        "options": map[string]interface{}{
            "format":    "A4",
            "wait_for":  2000,
            "full_page": true,
            "viewport": map[string]int{
                "width": 1920, "height": 1080,
            },
        },
    }

    body, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", "https://api.pdfapi.dev/v1/pdf/url", bytes.NewBuffer(body))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("PDFAPI_KEY"))
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    pdf, _ := io.ReadAll(resp.Body)
    os.WriteFile("report.pdf", pdf, 0644)
}

Wait for Dynamic Content

For pages with JavaScript-rendered content, use wait_for to ensure content loads:

{
  "url": "https://example.com/dashboard",
  "options": {
    "wait_for": 3000
  }
}

The wait_for value is in milliseconds. Maximum: 30,000ms (30 seconds).


Authentication with Cookies

For pages requiring authentication, pass session cookies:

{
  "url": "https://example.com/private/report",
  "options": {
    "cookies": [
      {
        "name": "session_id",
        "value": "abc123xyz",
        "domain": "example.com",
        "path": "/",
        "secure": true,
        "httpOnly": true
      }
    ]
  }
}
ParameterTypeRequiredDescription
namestringYesCookie name
valuestringYesCookie value
domainstringYesCookie domain
pathstringNoCookie path (default: /)
securebooleanNoHTTPS only
httpOnlybooleanNoHTTP only flag

Full Page Capture

Capture the entire scrollable page:

{
  "url": "https://example.com/long-page",
  "options": {
    "full_page": true
  }
}

Full page capture may result in multi-page PDFs for long pages.


Custom Viewport

Set a specific viewport size for responsive pages:

{
  "url": "https://example.com/responsive",
  "options": {
    "viewport": {
      "width": 1440,
      "height": 900
    }
  }
}

Common viewport sizes:

  • Desktop: 1920×1080, 1440×900
  • Tablet: 1024×768, 768×1024
  • Mobile: 390×844, 375×667

Limitations

  • Only publicly accessible URLs (or URLs accessible with provided cookies)
  • Maximum page load timeout: 30 seconds
  • JavaScript execution is supported
  • CAPTCHA-protected pages are not supported
  • Some SPAs may require longer wait_for values

Response

Success (200)

Content-Type: application/pdf
Content-Disposition: attachment; filename="document.pdf"

Error Responses

Invalid URL (400)

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Valid URL is required"
  }
}

Page Load Failed (500)

{
  "error": {
    "code": "PDF_GENERATION_ERROR",
    "message": "Failed to load URL",
    "details": {
      "reason": "Page load timeout after 30000ms"
    }
  }
}

URL Not Accessible (500)

{
  "error": {
    "code": "PDF_GENERATION_ERROR",
    "message": "URL is not accessible",
    "details": {
      "status_code": 403
    }
  }
}