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 | |
| 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.mediaacceptsscreen(default) andprint.- 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
- Dark mode screenshots emulate a different media feature,
prefers-color-scheme. - The browser options reference lists all emulation settings.
- To test a print capture on your own pages, create a free account.