NewIntroducing semantic snapshotsPair every capture with structured DOM data →

For products that run on customers' sites

Confirm your widget renders on every site that installed it

Load each customer's page, wait for your widget and capture only the widget, or learn that it never appeared.

The problem

Your chat widget, review carousel or booking form runs on hundreds of sites you do not control. A theme update hides it, a consent tool blocks it, a customer pastes the snippet into the wrong template, and the first sign is a support ticket asking why nothing has come in for a month.

How domscout handles it

waitForSelector waits for your widget's root element to appear and captureSelector crops the screenshot to it, so a success is a picture of the widget as visitors on that site see it. When the widget never appears, the request is refused with 400 WAIT_FOR_SELECTOR_TIMEOUT and nothing is charged, so a failed check is both free and unambiguous. Run it per site, or hand a batch the whole list.

Where it shows up

  • An onboarding step that confirms a new customer's install.
  • A weekly sweep of every site with the widget installed.
  • A picture of the widget on each customer's site for the support team.

The request

POST /screenshot. Available on every plan at 1 credit a site, and a refused check is refunded. Checking up to 100 sites in one request with /batch starts at Business.

cURL
curl -X POST https://api.domscout.io/screenshot \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://customer.example.com/",
    "waitForSelector": "#acme-widget",
    "captureSelector": "#acme-widget",
    "format": "png",
    "responseType": "binary"
  }' \
  -o widget.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({
    url: "https://customer.example.com/",
    waitForSelector: "#acme-widget",
    captureSelector: "#acme-widget",
    format: "png",
    responseType: "binary"
  }),
});
await writeFile("widget.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={
        "url": "https://customer.example.com/",
        "waitForSelector": "#acme-widget",
        "captureSelector": "#acme-widget",
        "format": "png",
        "responseType": "binary"
    },
)
with open("widget.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{
		"url": "https://customer.example.com/",
		"waitForSelector": "#acme-widget",
		"captureSelector": "#acme-widget",
		"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("widget.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([
        'url' => 'https://customer.example.com/',
        'waitForSelector' => '#acme-widget',
        'captureSelector' => '#acme-widget',
        'format' => 'png',
        'responseType' => 'binary'
    ]),
]);
$response = curl_exec($ch);
if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}
file_put_contents('widget.png', $response);
Ruby
require "json"
require "net/http"

response = Net::HTTP.post(
  URI("https://api.domscout.io/screenshot"),
  {
    url: "https://customer.example.com/",
    waitForSelector: "#acme-widget",
    captureSelector: "#acme-widget",
    format: "png",
    responseType: "binary"
  }.to_json,
  "Content-Type" => "application/json",
  "x-api-key" => "YOUR_API_KEY"
)
File.binwrite("widget.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 = """
            {
                "url": "https://customer.example.com/",
                "waitForSelector": "#acme-widget",
                "captureSelector": "#acme-widget",
                "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("widget.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 {
    url = "https://customer.example.com/",
    waitForSelector = "#acme-widget",
    captureSelector = "#acme-widget",
    format = "png",
    responseType = "binary"
});
await File.WriteAllBytesAsync("widget.png", await response.Content.ReadAsByteArrayAsync());

Go further

More in Testing and QA: Responsive layout checks · Visual regression testing · JavaScript error checks · Signup and checkout flow checks · Hover, focus and dark mode screenshots · Localization screenshots · Unlabelled control checks · A screenshot of every step · Screenshots for support tickets · Ad landing page checks · Before and after hydration · Selectors for test automation · Print layout checks · All use cases

Give your product a browser.

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