How to Capture Screenshots of Authenticated Pages with an API

Published March 1, 2026 · 10 min read

You need a screenshot of a dashboard. A client portal. An admin panel behind a login wall. You call a website screenshot API, pass the URL, and get back... a login page. Sound familiar?

Capturing screenshots of authenticated pages is one of the most common challenges developers face when automating visual workflows. The screenshot service has no session, no cookies, and no idea who you are. It just sees the same login form every visitor sees.

This guide covers every practical approach to solving this problem, with working code examples you can copy and adapt.

Why Authenticated Screenshots Are Tricky

When you visit a protected page in your browser, your session cookie does all the heavy lifting. The server checks it, confirms you're logged in, and serves the content. A screenshot API makes a fresh request with no cookies, so it gets redirected to the login page every time.

There are three main strategies to work around this:

  1. Pass cookies directly to the screenshot request
  2. Set custom headers (like Authorization or Bearer tokens)
  3. Inject JavaScript that handles login before the screenshot is taken

Which one you use depends on how the target application handles authentication.

Method 1: Passing Cookies

The most straightforward approach. If the app uses session cookies, you can extract your cookie string and pass it along with the screenshot request. GrabShot's cookies parameter accepts cookies in the standard Name=Value format.

curl

curl "https://grabshot.dev/api/screenshot" \
  -G \
  --data-urlencode "url=https://app.example.com/dashboard" \
  --data-urlencode "api_key=YOUR_API_KEY" \
  --data-urlencode "cookies=session_id=abc123def456; _csrf=token789" \
  --data-urlencode "width=1440" \
  --data-urlencode "height=900" \
  --output dashboard.png

Node.js

const fetch = require('node-fetch');
const fs = require('fs');

async function screenshotDashboard() {
  const params = new URLSearchParams({
    url: 'https://app.example.com/dashboard',
    api_key: process.env.GRABSHOT_API_KEY,
    cookies: 'session_id=abc123def456; _csrf=token789',
    width: '1440',
    height: '900',
    format: 'png'
  });

  const response = await fetch(
    `https://grabshot.dev/api/screenshot?${params}`
  );

  const buffer = Buffer.from(await response.arrayBuffer());
  fs.writeFileSync('dashboard.png', buffer);
  console.log('Screenshot saved');
}

screenshotDashboard();

Python

import requests
import os

response = requests.get('https://grabshot.dev/api/screenshot', params={
    'url': 'https://app.example.com/dashboard',
    'api_key': os.environ['GRABSHOT_API_KEY'],
    'cookies': 'session_id=abc123def456; _csrf=token789',
    'width': 1440,
    'height': 900,
    'format': 'png'
})

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

print('Screenshot saved')

How to Get Your Cookies

The simplest way: open DevTools in your browser (F12), go to the Application tab, and look under Cookies for the domain. Copy the relevant session cookies. For automation, you can programmatically log in first and extract the Set-Cookie headers from the response.

Here's how to automate cookie extraction in Node.js:

const fetch = require('node-fetch');

async function getSessionCookie() {
  // Log in to get a fresh session cookie
  const loginResponse = await fetch('https://app.example.com/api/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      email: '[email protected]',
      password: process.env.APP_PASSWORD
    }),
    redirect: 'manual'  // Don't follow redirects
  });

  // Extract Set-Cookie header
  const setCookie = loginResponse.headers.get('set-cookie');
  // Parse out the cookie value
  const sessionCookie = setCookie.split(';')[0];

  return sessionCookie;  // e.g. "session_id=abc123def456"
}

// Use it with the screenshot API
const cookies = await getSessionCookie();
// Pass to grabshot.dev/api/screenshot as the cookies parameter

Method 2: Custom Headers (Bearer Tokens, API Keys)

Many modern apps use token-based auth instead of cookies. SPAs built with React or Vue often send a JWT in the Authorization header. If that's your situation, you need to pass custom headers with the screenshot request.

GrabShot supports a headers parameter that lets you send arbitrary HTTP headers along with the page request:

curl

curl "https://grabshot.dev/api/screenshot" \
  -G \
  --data-urlencode "url=https://app.example.com/dashboard" \
  --data-urlencode "api_key=YOUR_API_KEY" \
  --data-urlencode "headers={\"Authorization\":\"Bearer eyJhbGciOi...\"}" \
  --output dashboard.png

Node.js

const params = new URLSearchParams({
  url: 'https://app.example.com/dashboard',
  api_key: process.env.GRABSHOT_API_KEY,
  headers: JSON.stringify({
    'Authorization': `Bearer ${process.env.JWT_TOKEN}`
  }),
  width: '1440',
  format: 'png'
});

const response = await fetch(
  `https://grabshot.dev/api/screenshot?${params}`
);

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

Method 3: JavaScript Injection for Complex Login Flows

Some apps have multi-step logins, CAPTCHA challenges, or OAuth flows that can't be solved with cookies or headers alone. For these cases, you can inject JavaScript that runs before the screenshot is taken.

The js parameter in GrabShot lets you execute custom JavaScript on the page. Combined with a delay, this can handle login forms:

const params = new URLSearchParams({
  url: 'https://app.example.com/login',
  api_key: process.env.GRABSHOT_API_KEY,
  js: `
    document.querySelector('#email').value = '[email protected]';
    document.querySelector('#password').value = 'secretpassword';
    document.querySelector('form').submit();
  `,
  delay: '5000',  // Wait 5s for login + redirect
  width: '1440',
  format: 'png'
});

const response = await fetch(
  `https://grabshot.dev/api/screenshot?${params}`
);

Important: Be careful with this approach. Hardcoding credentials in API calls is a security risk. Use environment variables, and consider whether the cookie or header method might be safer for your use case.

Common Use Cases

Client Reporting Dashboards

Agencies often need to screenshot client dashboards (Google Analytics, ad platforms, CRM systems) for automated reports. The typical flow is: log in once programmatically, capture the session cookie, then use it for multiple screenshots across different pages.

import requests
import os

API_KEY = os.environ['GRABSHOT_API_KEY']
SESSION_COOKIE = 'sid=your_session_cookie_here'

# Capture multiple dashboard pages in one batch
pages = [
    ('overview', 'https://analytics.example.com/overview'),
    ('traffic', 'https://analytics.example.com/traffic'),
    ('conversions', 'https://analytics.example.com/conversions'),
]

for name, url in pages:
    response = requests.get('https://grabshot.dev/api/screenshot', params={
        'url': url,
        'api_key': API_KEY,
        'cookies': SESSION_COOKIE,
        'width': 1440,
        'height': 900,
        'format': 'png'
    })

    with open(f'{name}.png', 'wb') as f:
        f.write(response.content)

    print(f'Captured {name}')

Internal Tool Documentation

Need to keep documentation up to date with screenshots of your internal tools? Automate it. Run a weekly script that logs in, captures key screens, and updates your docs repo.

Visual Regression Testing Behind Auth

If you're running visual regression tests on an authenticated app, you need every test screenshot to be logged in. Pass the session cookie as part of your CI pipeline, and compare screenshots between deployments.

Security Best Practices

When passing credentials through a screenshot API, keep these in mind:

Troubleshooting

ProblemSolution
Still seeing login pageCookie may have expired. Extract a fresh one and retry.
Blank page after loginSPA might need more load time. Increase the delay parameter.
CSRF token errorsInclude the CSRF cookie along with the session cookie.
OAuth redirect loopOAuth tokens usually need the header method, not cookies. Try passing the Bearer token instead.
2FA blocking loginUse app passwords or API tokens that bypass 2FA. Most services offer these for automation.

Try It Free

GrabShot gives you 25 free screenshots per month. Test authenticated page capture with your own apps.

Get Your API Key

Wrapping Up

Capturing screenshots behind authentication boils down to giving the screenshot API the same credentials your browser uses. Cookies work for traditional session-based apps. Bearer tokens work for modern SPAs. JavaScript injection handles the edge cases.

Start with the simplest method that works for your target app, and layer on security best practices as you move to production. If you're building automated reports, CI pipelines, or documentation workflows, authenticated screenshots are a solved problem.

Check out the GrabShot documentation for full API reference, including all available parameters for cookies, headers, and JavaScript injection.