NewIntroducing semantic snapshotsPair every capture with structured DOM data →

For walkthroughs, QA evidence and bug reports

Get a picture of every step in a user flow

Run a flow of clicks and typing and get a screenshot before the first step and after every step that completes.

The problem

A bug report that says "checkout broke" is not much to go on. Neither is a QA sign-off with no evidence, or an onboarding guide whose screenshots were taken by hand in an order the product no longer follows.

How domscout handles it

With captureTimeline on, the request takes a screenshot before the first action and another after each action that completes, and returns them in order in timelineBase64, next to the per-step results in actionResults. Flows like this can outlast a direct request, so send async: true and collect the frames from the job when it finishes.

Where it shows up

  • Step-by-step images for an onboarding guide.
  • Evidence attached to a QA sign-off.
  • A bug report that shows exactly where a flow went wrong.

The request

POST /screenshot. Timeline capture starts at Business and adds 2 credits, so this request costs 3. With async: true the response is a job, and GET /job/{jobId} returns the frames when it finishes.

cURL
curl -X POST https://api.domscout.io/screenshot \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/",
    "captureTimeline": true,
    "async": true,
    "responseType": "json",
    "actions": [
      {"action": "click", "selector": "a[href='\''/pricing'\'']"},
      {"action": "wait", "time": 1000},
      {"action": "click", "selector": "a[href='\''/signup'\'']"},
      {"action": "wait", "time": 1000}
    ]
  }'
Node.js
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://www.example.com/",
    captureTimeline: true,
    async: true,
    responseType: "json",
    actions: [
      { action: "click", selector: "a[href='/pricing']" },
      { action: "wait", time: 1000 },
      { action: "click", selector: "a[href='/signup']" },
      { action: "wait", time: 1000 }
    ]
  }),
});
console.log(await response.json());
Python
import requests

response = requests.post(
    "https://api.domscout.io/screenshot",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "url": "https://www.example.com/",
        "captureTimeline": True,
        "async": True,
        "responseType": "json",
        "actions": [
            {"action": "click", "selector": "a[href='/pricing']"},
            {"action": "wait", "time": 1000},
            {"action": "click", "selector": "a[href='/signup']"},
            {"action": "wait", "time": 1000}
        ]
    },
)
print(response.json())
Go
package main

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

func main() {
	body, _ := json.Marshal(map[string]any{
		"url": "https://www.example.com/",
		"captureTimeline": true,
		"async": true,
		"responseType": "json",
		"actions": []any{
			map[string]any{"action": "click", "selector": "a[href='/pricing']"},
			map[string]any{"action": "wait", "time": 1000},
			map[string]any{"action": "click", "selector": "a[href='/signup']"},
			map[string]any{"action": "wait", "time": 1000},
		},
	})
	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()

	raw, _ := io.ReadAll(res.Body)
	fmt.Println(string(raw))
}
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://www.example.com/',
        'captureTimeline' => true,
        'async' => true,
        'responseType' => 'json',
        'actions' => [
            ['action' => 'click', 'selector' => 'a[href=\'/pricing\']'],
            ['action' => 'wait', 'time' => 1000],
            ['action' => 'click', 'selector' => 'a[href=\'/signup\']'],
            ['action' => 'wait', 'time' => 1000]
        ]
    ]),
]);
$response = curl_exec($ch);
if ($response === false) {
    throw new RuntimeException(curl_error($ch));
}
echo $response;
Ruby
require "json"
require "net/http"

response = Net::HTTP.post(
  URI("https://api.domscout.io/screenshot"),
  {
    url: "https://www.example.com/",
    captureTimeline: true,
    async: true,
    responseType: "json",
    actions: [
      { action: "click", selector: "a[href='/pricing']" },
      { action: "wait", time: 1000 },
      { action: "click", selector: "a[href='/signup']" },
      { action: "wait", time: 1000 }
    ]
  }.to_json,
  "Content-Type" => "application/json",
  "x-api-key" => "YOUR_API_KEY"
)
puts response.body
Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Capture {
    public static void main(String[] args) throws Exception {
        String body = """
            {
                "url": "https://www.example.com/",
                "captureTimeline": true,
                "async": true,
                "responseType": "json",
                "actions": [
                    {
                        "action": "click",
                        "selector": "a[href='/pricing']"
                    },
                    {"action": "wait", "time": 1000},
                    {"action": "click", "selector": "a[href='/signup']"},
                    {"action": "wait", "time": 1000}
                ]
            }
            """;
        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<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(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://www.example.com/",
    captureTimeline = true,
    async = true,
    responseType = "json",
    actions = new[] {
        new { action = "click", selector = "a[href='/pricing']" },
        new { action = "wait", time = 1000 },
        new { action = "click", selector = "a[href='/signup']" },
        new { action = "wait", time = 1000 }
    }
});
Console.WriteLine(await response.Content.ReadAsStringAsync());

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 · Embedded widget checks · 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.