ChartQuery

Screenshot a Webpage

Capture a full-page or viewport screenshot of any URL as a PNG or JPEG file using the CaptureKit API — no headless browser to maintain.

Overview

This playbook shows how to take a screenshot of any public URL and save it to disk. A common use case is visual regression testing or generating OG image thumbnails for a link-preview service.

Prerequisites

  • A CaptureKit API key — get one at app.capturekit.dev
  • Install dependencies for your language:
pip install requests

No extra dependencies — uses the native fetch API (Node 18+).

curl extension enabled (on by default).

No extra dependencies — uses net/http (Go 1.18+).

No extra dependencies — uses java.net.http (Java 11+).

No extra dependencies — uses System.Net.Http (.NET 6+).

# Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde_json = "1"

Steps

Request a screenshot

Call GET /v1/capture with the url parameter. Additional options control the viewport, format, and full-page capture.

import requests

API_KEY = "YOUR_API_KEY"

response = requests.get(
    "https://api.capturekit.dev/v1/capture",
    headers={"x-api-key": API_KEY},
    params={
        "url":       "https://stripe.com",
        "format":    "png",
        "full_page": "true",
        "width":     "1440",
        "height":    "900",
    },
)
data = response.json()
print(data)
const API_KEY = "YOUR_API_KEY";

const params = new URLSearchParams({
  url:       "https://stripe.com",
  format:    "png",
  full_page: "true",
  width:     "1440",
  height:    "900",
});

const response = await fetch(`https://api.capturekit.dev/v1/capture?${params}`, {
  headers: { "x-api-key": API_KEY },
});
const data = await response.json();
console.log(data);
<?php
$apiKey = "YOUR_API_KEY";
$params = http_build_query([
    "url"       => "https://stripe.com",
    "format"    => "png",
    "full_page" => "true",
    "width"     => "1440",
    "height"    => "900",
]);

$ch = curl_init("https://api.capturekit.dev/v1/capture?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: {$apiKey}"]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($data);
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
)

func main() {
    params := url.Values{
        "url": {"https://stripe.com"}, "format": {"png"},
        "full_page": {"true"}, "width": {"1440"}, "height": {"900"},
    }
    req, _ := http.NewRequest("GET", "https://api.capturekit.dev/v1/capture?"+params.Encode(), nil)
    req.Header.Set("x-api-key", "YOUR_API_KEY")

    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)

    var data map[string]any
    json.Unmarshal(body, &data)
    fmt.Println(data)
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;

var apiKey = "YOUR_API_KEY";
var target = URLEncoder.encode("https://stripe.com", StandardCharsets.UTF_8);
var url    = "https://api.capturekit.dev/v1/capture?url=" + target + "&format=png&full_page=true&width=1440&height=900";

var client  = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder().uri(URI.create(url))
    .header("x-api-key", apiKey).GET().build();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
using System.Net.Http;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");

var target = Uri.EscapeDataString("https://stripe.com");
var body   = await client.GetStringAsync(
    $"https://api.capturekit.dev/v1/capture?url={target}&format=png&full_page=true&width=1440&height=900");
Console.WriteLine(body);
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let data = reqwest::Client::new()
        .get("https://api.capturekit.dev/v1/capture")
        .header("x-api-key", "YOUR_API_KEY")
        .query(&[("url", "https://stripe.com"), ("format", "png"), ("full_page", "true"), ("width", "1440"), ("height", "900")])
        .send().await?.json::<serde_json::Value>().await?;

    println!("{:#?}", data);
    Ok(())
}

Get the image URL from the response

The API returns a screenshot_url with the hosted image — or a base64-encoded image field if you set response_type=base64.

screenshot_url = data.get("screenshot_url")
print(f"Screenshot ready: {screenshot_url}")
const { screenshot_url } = data;
console.log(`Screenshot ready: ${screenshot_url}`);
$screenshotUrl = $data["screenshot_url"] ?? "";
echo "Screenshot ready: {$screenshotUrl}\n";
screenshotURL := data["screenshot_url"].(string)
fmt.Println("Screenshot ready:", screenshotURL)
import org.json.*;

var screenshotUrl = new JSONObject(response.body()).getString("screenshot_url");
System.out.println("Screenshot ready: " + screenshotUrl);
using System.Text.Json;

var screenshotUrl = JsonDocument.Parse(body).RootElement.GetProperty("screenshot_url").GetString();
Console.WriteLine($"Screenshot ready: {screenshotUrl}");
let screenshot_url = data["screenshot_url"].as_str().unwrap_or("");
println!("Screenshot ready: {}", screenshot_url);

Download and save the image

Fetch the image bytes from the URL and write them to disk.

filename = "screenshot.png"
with requests.get(screenshot_url, stream=True) as r:
    r.raise_for_status()
    with open(filename, "wb") as f:
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)

print(f"Saved to {filename}")
import { writeFileSync } from "fs";

const imgResponse = await fetch(screenshotUrl);
const buffer      = Buffer.from(await imgResponse.arrayBuffer());
writeFileSync("screenshot.png", buffer);
console.log("Saved to screenshot.png");
$fp = fopen("screenshot.png", "wb");
$ch = curl_init($screenshotUrl);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);
fclose($fp);
echo "Saved to screenshot.png\n";
import "os"

resp, _ := http.Get(screenshotURL)
defer resp.Body.Close()
file, _ := os.Create("screenshot.png")
defer file.Close()
io.Copy(file, resp.Body)
fmt.Println("Saved to screenshot.png")
import java.net.URL;
import java.nio.file.*;

Files.copy(new URL(screenshotUrl).openStream(), Path.of("screenshot.png"), StandardCopyOption.REPLACE_EXISTING);
System.out.println("Saved to screenshot.png");
var imageBytes = await new HttpClient().GetByteArrayAsync(screenshotUrl);
File.WriteAllBytes("screenshot.png", imageBytes);
Console.WriteLine("Saved to screenshot.png");
use std::{fs::File, io::Write};

let bytes = reqwest::get(screenshot_url).await?.bytes().await?;
let mut file = File::create("screenshot.png").unwrap();
file.write_all(&bytes).unwrap();
println!("Saved to screenshot.png");

Use full_page=false to capture only the above-the-fold viewport — ideal for social media preview thumbnails where a fixed-height 630×1200 px crop is required.

On this page