Full-page screenshots

A full-page screenshot captures the whole scrollable document at the viewport width you choose. The image is as tall as the page, up to capture.scroll.max_height. This guide is part of the capture guides. For a comparison with Puppeteer, Playwright, Selenium and browser tools, read full page screenshots: every method tested.

The minimal request

The examples read your key from RS_API_KEY. If you do not have a key, create a free account first.

With GET, use the full_page preset. It sets full-page mode and turns on scroll simulation:

curl -G "https://api.renderscreenshot.com/v1/screenshot" \
  -H "Authorization: Bearer $RS_API_KEY" \
  --data-urlencode "url=https://example.com" \
  --data-urlencode "preset=full_page" \
  -o full-page.png

full_page=true also works in GET, but it only sets capture.mode. Scroll simulation stays off, so lazy images below the first screen can stay empty.

With POST, set the mode and the scroll options in capture:

curl -X POST https://api.renderscreenshot.com/v1/screenshot \
  -H "Authorization: Bearer $RS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "capture": {
      "mode": "full_page",
      "scroll": { "simulate": true, "delay": 400 }
    }
  }' \
  -o full-page.png

Parameters that matter

Parameter Default Notes
capture.mode viewport Set to full_page. GET: full_page=true or preset=full_page.
capture.scroll.simulate false Scrolls through the page before the capture so lazy loaders fire. The full_page preset sets it to true.
capture.scroll.step viewport height Pixels per scroll step. Smaller steps trigger observers with small margins; more steps take longer.
capture.scroll.delay 400 Milliseconds to wait at each step. Raise it when images arrive slowly.
capture.scroll.max_height 16000 Maximum capture height in pixels. Content below it is not captured.
capture.beyond_viewport true Captures content outside the visible window.
viewport.width 1280 The page height depends on the width: narrow layouts are taller. 1 to 7,680.
viewport.scale 1 2 doubles the pixel height of the image as well as the width.
wait.until / wait.delay load / 0 Applied before the scroll. wait.delay is capped at 10,000 ms.
wait.timeout 30 Seconds for the whole render, maximum 60. Long pages with a slow scroll need more.

Only full_page and preset exist as GET parameters. scroll.step, scroll.delay and scroll.max_height need POST. See the capture parameter reference.

Estimate the scroll time

The scroll takes about (page height / step) x delay. A 12,000 px page at the default step of 800 px and the default delay of 400 ms needs 15 steps, about 6 seconds, before the capture starts. Keep that below wait.timeout, together with the page load.

Tune the scroll for slow images

When the bottom images of a page are still empty, the scroll moved on before they arrived. Give each step more time, and use a step smaller than the viewport so each image is on screen during at least one pause:

{
  "url": "https://example.com/gallery",
  "capture": {
    "mode": "full_page",
    "scroll": { "simulate": true, "step": 600, "delay": 800, "max_height": 12000 }
  },
  "wait": { "until": "networkidle", "timeout": 60 }
}

networkidle waits until no request has run for 500 ms, which helps the last images finish after the scroll.

Remove fixed bars before the capture

A fixed cookie bar or chat button is drawn once, where the first screen ends, on top of the content. Remove it in the same request with page modifications:

{
  "url": "https://example.com",
  "capture": { "mode": "full_page", "scroll": { "simulate": true } },
  "block": { "cookie_banners": true },
  "page": {
    "remove": [".chat-launcher"],
    "styles": ["header.site-header { position: absolute !important; }"]
  }
}

The sticky header article explains each failure mode, and block ads and cookie banners covers block.cookie_banners.

SDK examples

All six SDKs have fullPage() (Python and Ruby: full_page) and preset(). Use the preset to get scroll simulation. The builders have no methods for scroll.step, scroll.delay or scroll.max_height; send those in a raw POST body as shown above.

Node.js

import { writeFile } from 'node:fs/promises';
import { Client, TakeOptions } from 'renderscreenshot';

const client = new Client(process.env.RS_API_KEY);

const image = await client.take(
  TakeOptions.url('https://example.com')
    .preset('full_page')
    .format('webp')
    .quality(80)
);
await writeFile('full-page.webp', image);

Python

import os
from renderscreenshot import Client, TakeOptions

client = Client(os.environ['RS_API_KEY'])

image = client.take(
    TakeOptions.url('https://example.com')
    .preset('full_page')
    .format('webp')
    .quality(80)
)
with open('full-page.webp', 'wb') as f:
    f.write(image)

Ruby

require 'renderscreenshot'

client = RenderScreenshot.client(ENV.fetch('RS_API_KEY'))

image = client.take(
  RenderScreenshot::TakeOptions
    .url('https://example.com')
    .preset('full_page')
    .format('webp')
    .quality(80)
)
File.binwrite('full-page.webp', image)

PHP

use RenderScreenshot\Client;
use RenderScreenshot\TakeOptions;

$client = new Client(getenv('RS_API_KEY'));

$image = $client->take(
    TakeOptions::url('https://example.com')
        ->preset('full_page')
        ->format('webp')
        ->quality(80)
);
file_put_contents('full-page.webp', $image);

Java

Client client = new Client(System.getenv("RS_API_KEY"));

byte[] image = client.take(
    TakeOptions.url("https://example.com")
        .preset("full_page")
        .format("webp")
        .quality(80)
);
Files.write(Path.of("full-page.webp"), image);

Go

client, err := rs.New(os.Getenv("RS_API_KEY"))
if err != nil {
    log.Fatal(err)
}

image, err := client.Take(ctx,
    rs.URL("https://example.com").
        Preset("full_page").
        Format(rs.FormatWebP).
        Quality(80),
)
if err != nil {
    log.Fatal(err)
}
os.WriteFile("full-page.webp", image, 0o644)

WebP or JPEG keeps long captures small. A full page at scale 2 has four times the pixels of the same page at 1x; see retina screenshots.

Troubleshooting

Symptom Likely cause Fix
Grey boxes or placeholders below the first screen Scroll simulation is off (full_page=true alone) Use preset=full_page or capture.scroll.simulate: true
The last images are still empty Each step moved on before the images arrived Raise scroll.delay, lower scroll.step, add wait.until: networkidle
Image ends before the page does scroll.max_height reached (16,000 px by default) Raise max_height, or capture one part with element mode
Feed or search page never seems to end Infinite scroll adds content at every step Set a lower max_height, for example 8,000
Cookie bar in the middle of the image A fixed bar is drawn where the first screen ended block.cookie_banners: true or page.remove
Header repeated or covering content Fixed or sticky header page.styles with position: absolute !important
Hero section is much taller than in the browser The section uses 100vh Set a pixel height with page.styles
Request times out on long pages Scroll time plus load time is above wait.timeout Raise wait.timeout (max 60) or shorten the scroll with a larger step
Image is wider than expected Content wider than the viewport Fix the width with viewport.width

Limits

  • capture.scroll.max_height defaults to 16,000 px. In our browser tests, full Chrome repeated the top of the page after 16,384 device pixels, so check the bottom of the image if you raise it.
  • viewport.width accepts 1 to 7,680 px and viewport.scale 1 to 3.
  • wait.timeout is 30 seconds by default and 60 at most. wait.delay is capped at 10,000 ms.
  • One full-page capture is one render and uses one credit.

Related in this topic

Was this page helpful?