NewIntroducing semantic snapshotsPair every capture with structured DOM data →

For products that draw their own images

Lay out social cards and certificates in HTML, get a PNG back

Lay the image out in HTML and CSS, send it in the request, and get back a PNG at exactly the size you set.

The problem

Every blog post needs an Open Graph card, every course completion a certificate, every release a social image. Designing each one in an image editor does not scale, drawing them with a canvas library means relearning layout that CSS already does well, and running a rendering service of your own is one more thing to deploy and patch.

How domscout handles it

Send the markup as html instead of a url and set the viewport to the size the image must be: 1200 by 630 for an Open Graph card. Chromium lays it out, waits for the network to go quiet so the fonts and images it links to have arrived, and returns the picture. deviceScaleFactor: 1 keeps the file exactly the viewport size, captureSelector crops to one element when the card is part of a larger page, and render.transparentBackground leaves out the page background for a PNG you can place on anything.

Where it shows up

  • An Open Graph image for every post, generated when it is published.
  • Certificates and badges rendered from a course or event record.
  • Share images for pages your users create: profiles, listings, playlists.

The request

POST /screenshot. Image output is on every plan, including the free Hobby plan, at 1 credit an image. The image is the viewport size multiplied by deviceScaleFactor, which defaults to 2. A request can carry up to 1,000,000 characters of HTML. Transparent backgrounds, under render, start at Pro.

cURL
curl -X POST https://api.domscout.io/screenshot \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
    "width": 1200,
    "height": 630,
    "deviceScaleFactor": 1,
    "format": "png",
    "responseType": "binary"
  }' \
  -o card.png
Node.js
import { writeFile } from "node:fs/promises";

const response = await fetch("https://api.domscout.io/screenshot", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-api-key": "YOUR_API_KEY" },
  body: JSON.stringify({
    html: "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
    width: 1200,
    height: 630,
    deviceScaleFactor: 1,
    format: "png",
    responseType: "binary"
  }),
});
await writeFile("card.png", Buffer.from(await response.arrayBuffer()));
Python
import requests

response = requests.post(
    "https://api.domscout.io/screenshot",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "html": "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
        "width": 1200,
        "height": 630,
        "deviceScaleFactor": 1,
        "format": "png",
        "responseType": "binary"
    },
)
with open("card.png", "wb") as f:
    f.write(response.content)
Go
package main

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"os"
)

func main() {
	body, _ := json.Marshal(map[string]any{
		"html": "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
		"width": 1200,
		"height": 630,
		"deviceScaleFactor": 1,
		"format": "png",
		"responseType": "binary",
	})
	req, _ := http.NewRequest("POST", "https://api.domscout.io/screenshot", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-api-key", "YOUR_API_KEY")

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

	out, _ := os.Create("card.png")
	defer out.Close()
	io.Copy(out, res.Body)
}
PHP
<?php
$ch = curl_init('https://api.domscout.io/screenshot');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'x-api-key: YOUR_API_KEY'],
    CURLOPT_POSTFIELDS => json_encode([
        'html' => '<body style="margin:0"><div style="width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif">Release notes: October</div></body>',
        'width' => 1200,
        'height' => 630,
        'deviceScaleFactor' => 1,
        'format' => 'png',
        'responseType' => 'binary'
    ]),
]);
$response = curl_exec($ch);
if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}
file_put_contents('card.png', $response);
Ruby
require "json"
require "net/http"

response = Net::HTTP.post(
  URI("https://api.domscout.io/screenshot"),
  {
    html: "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
    width: 1200,
    height: 630,
    deviceScaleFactor: 1,
    format: "png",
    responseType: "binary"
  }.to_json,
  "Content-Type" => "application/json",
  "x-api-key" => "YOUR_API_KEY"
)
File.binwrite("card.png", response.body)
Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;

public class Capture {
    public static void main(String[] args) throws Exception {
        String body = """
            {
                "html": "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
                "width": 1200,
                "height": 630,
                "deviceScaleFactor": 1,
                "format": "png",
                "responseType": "binary"
            }
            """;
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.domscout.io/screenshot"))
            .header("Content-Type", "application/json")
            .header("x-api-key", "YOUR_API_KEY")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        HttpResponse<Path> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofFile(Path.of("card.png")));
        System.out.println("Saved " + response.body());
    }
}
C#
using System.Net.Http.Json;

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

var response = await client.PostAsJsonAsync("https://api.domscout.io/screenshot", new {
    html = "<body style=\"margin:0\"><div style=\"width:1200px;height:630px;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#fff;font:700 64px sans-serif\">Release notes: October</div></body>",
    width = 1200,
    height = 630,
    deviceScaleFactor = 1,
    format = "png",
    responseType = "binary"
});
await File.WriteAllBytesAsync("card.png", await response.Content.ReadAsByteArrayAsync());

Go further

More in Screenshots, images and PDFs: Thumbnails and link previews · PDFs from your own HTML · Web page to PDF · Screenshots of a list of URLs · Product screenshots for docs · Dashboard screenshots to chat · Monthly reports for clients · Email template previews · Full-page captures for review tools · All use cases

Give your product a browser.

Get clean web content and visual proof into your workflow in minutes.