NewIntroducing semantic snapshotsPair every capture with structured DOM data →

For teams watching something

Find out that a page changed before your customer tells you

Capture a page on a schedule, compare what it says rather than its markup, and get a signed webhook when it changes.

The problem

Something on the open web matters to your business and nobody owns watching it: a competitor's pricing page, a regulator's guidance note, a partner's API status page, your own checkout after a deploy. The usual answer is a cron job that diffs raw HTML, which means it fires every time a build hash or an ad slot changes, and everyone learns to ignore it.

How domscout handles it

A monitor captures the page on a schedule and keeps the history. It compares what the page says (the extracted text, the title, the links and the status code) rather than the raw markup, so a new build hash in a script or stylesheet URL is not a change and a reworded refund policy is. When it does change, a signed webhook names the run, the two captures and the fields that changed.

Where it shows up

  • Competitive pricing alerts that go to a channel people still read.
  • Compliance and policy watch on documents you do not control.
  • Post-deploy checks on the handful of pages that must never break.

The request

POST /monitors. Monitors start at Pro: 10 monitors, checked as often as every 60 minutes. Business allows 100 every 15 minutes and Enterprise 500 every 5, subject to the service's launch controls.

cURL
curl -X POST https://api.domscout.io/monitors \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Competitor pricing",
    "targetUrl": "https://example.com/pricing",
    "intervalMinutes": 60,
    "notifyWebhookUrl": "https://your-app.example/hooks/domscout"
  }'
Node.js
const response = await fetch("https://api.domscout.io/monitors", {
  method: "POST",
  headers: { "Content-Type": "application/json", "x-api-key": "YOUR_API_KEY" },
  body: JSON.stringify({
    name: "Competitor pricing",
    targetUrl: "https://example.com/pricing",
    intervalMinutes: 60,
    notifyWebhookUrl: "https://your-app.example/hooks/domscout"
  }),
});
console.log(await response.json());
Python
import requests

response = requests.post(
    "https://api.domscout.io/monitors",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "name": "Competitor pricing",
        "targetUrl": "https://example.com/pricing",
        "intervalMinutes": 60,
        "notifyWebhookUrl": "https://your-app.example/hooks/domscout"
    },
)
print(response.json())
Go
package main

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

func main() {
	body, _ := json.Marshal(map[string]any{
		"name": "Competitor pricing",
		"targetUrl": "https://example.com/pricing",
		"intervalMinutes": 60,
		"notifyWebhookUrl": "https://your-app.example/hooks/domscout",
	})
	req, _ := http.NewRequest("POST", "https://api.domscout.io/monitors", 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/monitors');
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([
        'name' => 'Competitor pricing',
        'targetUrl' => 'https://example.com/pricing',
        'intervalMinutes' => 60,
        'notifyWebhookUrl' => 'https://your-app.example/hooks/domscout'
    ]),
]);
$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/monitors"),
  {
    name: "Competitor pricing",
    targetUrl: "https://example.com/pricing",
    intervalMinutes: 60,
    notifyWebhookUrl: "https://your-app.example/hooks/domscout"
  }.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 = """
            {
                "name": "Competitor pricing",
                "targetUrl": "https://example.com/pricing",
                "intervalMinutes": 60,
                "notifyWebhookUrl": "https://your-app.example/hooks/domscout"
            }
            """;
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.domscout.io/monitors"))
            .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/monitors", new {
    name = "Competitor pricing",
    targetUrl = "https://example.com/pricing",
    intervalMinutes = 60,
    notifyWebhookUrl = "https://your-app.example/hooks/domscout"
});
Console.WriteLine(await response.Content.ReadAsStringAsync());

Go further

Other use cases: Web access for AI agents · Web archiving and evidence · Crawling a whole site · SEO regression checks · Thumbnails and link previews · PDFs from your own HTML · Structured data from web pages · Link preview checks · Responsive layout checks

Give your product a browser.

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