Print media screenshots

Set browser.media to print and the screenshot shows the page as its print stylesheet styles it: navigation hidden, ads gone, link URLs written out, whatever the site's @media print rules say. You get an image, not pages. This guide shows the request and the three ways a print screenshot differs from a PDF. More guides are on the guides hub.

Last verified on 2026-10-15 against the renderer source and a local Puppeteer 24.43.1 (Chrome 148) replay of the same browser call.

When to use it

  • An article or documentation page has a clean print layout and you want it as one tall image.
  • You check what visitors get when they press Ctrl+P, and you want a picture in a review or a test report.
  • A dashboard hides its controls in print, and you want the data without the chrome.

If you need page breaks, paper sizes or margins, request a PDF instead. The PDF options cover paper size, margins, headers and footers.

The request

browser.media is a POST option. The GET endpoint does not map a media query parameter.

curl

curl -sS --fail -X POST https://api.renderscreenshot.com/v1/screenshot \
  -H "Authorization: Bearer $RS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "url": "https://example.com",
      "browser": {
        "media": "print"
      },
      "capture": {
        "mode": "full_page"
      }
    }' \
  -o print.png

Node.js

import { writeFile } from 'node:fs/promises';

const body = {
  "url": "https://example.com",
  "browser": {
    "media": "print"
  },
  "capture": {
    "mode": "full_page"
  }
};

const res = await fetch('https://api.renderscreenshot.com/v1/screenshot', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.RS_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(body),
});

if (!res.ok) {
  console.error(res.status, await res.text());
  process.exit(1);
}

await writeFile('print.png', Buffer.from(await res.arrayBuffer()));

Python

import json
import os
import sys
import urllib.error
import urllib.request

body = {
    'url': 'https://example.com',
    'browser': {
        'media': 'print',
    },
    'capture': {
        'mode': 'full_page',
    },
}

req = urllib.request.Request(
    'https://api.renderscreenshot.com/v1/screenshot',
    data=json.dumps(body).encode(),
    headers={
        'Authorization': f"Bearer {os.environ['RS_API_KEY']}",
        'Content-Type': 'application/json',
    },
    method='POST',
)

try:
    with urllib.request.urlopen(req, timeout=90) as res:
        with open('print.png', 'wb') as f:
            f.write(res.read())
except urllib.error.HTTPError as err:
    sys.exit(f'{err.code} {err.read().decode()}')

Ruby

require 'json'
require 'net/http'

body = {
  url: 'https://example.com',
  browser: {
    media: 'print'
  },
  capture: {
    mode: 'full_page'
  }
}

uri = URI('https://api.renderscreenshot.com/v1/screenshot')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV.fetch('RS_API_KEY')}"
request['Content-Type'] = 'application/json'
request.body = body.to_json

response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', read_timeout: 90) do |http|
  http.request(request)
end
abort("#{response.code} #{response.body}") unless response.is_a?(Net::HTTPSuccess)

File.binwrite('print.png', response.body)

PHP

<?php

$body = [
    'url' => 'https://example.com',
    'browser' => [
        'media' => 'print',
    ],
    'capture' => [
        'mode' => 'full_page',
    ],
];

$ch = curl_init('https://api.renderscreenshot.com/v1/screenshot');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RS_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($body, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 90,
]);

$image = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($image === false || $status !== 200) {
    fwrite(STDERR, $status . ' ' . ($image === false ? curl_error($ch) : $image) . "\n");
    exit(1);
}

file_put_contents('print.png', $image);

Go

package main

import (
    "bytes"
    "io"
    "log"
    "net/http"
    "os"
)

const body = `{
  "url": "https://example.com",
  "browser": {
    "media": "print"
  },
  "capture": {
    "mode": "full_page"
  }
}`

func main() {
    req, err := http.NewRequest(http.MethodPost, "https://api.renderscreenshot.com/v1/screenshot", bytes.NewBufferString(body))
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Authorization", "Bearer "+os.Getenv("RS_API_KEY"))
    req.Header.Set("Content-Type", "application/json")

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    data, err := io.ReadAll(res.Body)
    if err != nil {
        log.Fatal(err)
    }
    if res.StatusCode != http.StatusOK {
        log.Fatalf("%d %s", res.StatusCode, data)
    }

    if err := os.WriteFile("print.png", data, 0o644); err != nil {
        log.Fatal(err)
    }
}

Java

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;

public class Capture {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "url": "https://example.com",
              "browser": {
                "media": "print"
              },
              "capture": {
                "mode": "full_page"
              }
            }
            """;

        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.renderscreenshot.com/v1/screenshot"))
            .header("Authorization", "Bearer " + System.getenv("RS_API_KEY"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

        HttpResponse<byte[]> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofByteArray());
        if (response.statusCode() != 200) {
            System.err.println(response.statusCode() + " " + new String(response.body()));
            System.exit(1);
        }

        Files.write(Path.of("print.png"), response.body());
    }
}

capture.mode: full_page is optional. Print stylesheets often remove sidebars and sticky headers, so the page gets taller and narrower in content. A full-page capture shows all of it.

What changes and what does not

The renderer calls the browser's media-type emulation before the page loads, so the page's JavaScript and CSS see print media from the start. We replayed that call on a test page with a @media print block, an @page rule and a red body background. Results:

Item In the screenshot
@media print rules (hide nav, show print-only blocks) Applied
a[href]::after { content: attr(href) } Applied, URLs appear after links
matchMedia('print').matches in page scripts true
Background colors and images Still drawn. The body stayed rgb(200, 0, 0) in the PNG
@page { size: A4; margin: 2cm } Ignored. The width stays the viewport width, 1280 px
Page breaks (break-before, break-inside) Ignored. The result is one continuous image

The background row surprises people. When you print, the browser drops backgrounds unless "Background graphics" is on. A screenshot is not a print job, so backgrounds stay. If you want the printed look, add a style that removes them:

{
  "url": "https://example.com",
  "browser": { "media": "print" },
  "page": {
    "styles": ["*, *::before, *::after { background: transparent !important; box-shadow: none !important; }"]
  }
}

Pick the viewport for the print layout

A print stylesheet assumes paper of about 600 to 800 CSS pixels wide, and the screenshot uses your viewport width. A 1280 px viewport can leave a narrow text column with wide empty margins. Set viewport.width near the width of the printed text, for example 800, to get an image that looks like the printed page.

Screenshot or PDF?

You want Use
One image of the print layout, for review or comparison browser.media: "print" with PNG or WebP
A document with page breaks, paper size and margins output.format: "pdf"
Selectable text and links PDF
A thumbnail of a printable page Print screenshot, then a smaller viewport

Troubleshooting

Symptom Cause Fix
Screenshot looks the same as screen mode The site has no print stylesheet, or the request was a GET Check the site with Ctrl+P. Use POST with browser.media.
invalid_media_type error A value other than screen or print Send exactly print or screen.
Wide empty margins around the text Print CSS sets a narrow column Lower viewport.width.
Backgrounds appear that the printout does not have Screenshots always paint backgrounds Add the transparent-background style above.
Content cut at a page break in the PDF but not in the image Page breaks apply only to PDF Expected. Use the PDF for paged output.

Limits

  • browser.media accepts screen (default) and print.
  • The viewport width can be 1 to 7,680 px.
  • The page must load within wait.timeout, which is 30 seconds by default and 60 at most.

Related in this topic

Was this page helpful?