NewIntroducing semantic snapshotsPair every capture with structured DOM data →

For security and trust teams

See what a suspicious link does without opening it on your machine

Open a reported link in a remote browser and get a picture, the text, the redirect chain and every domain it contacted.

The problem

A customer forwards a message that claims to be from you, with a link in it. Someone has to find out where it goes, what it shows and whether it asks for a password, and opening it on a work laptop is exactly what the sender wants.

How domscout handles it

The link opens in domscout's browser, on domscout's servers, not on the analyst's machine. Private and internal network addresses are refused, and every redirect is checked again before it is followed. The response carries a screenshot of what loaded, the page as Markdown and markdownMeta.finalUrl for where the redirects ended; with diagnostics it also lists the redirect chain and every other domain the page contacted, and metadata.accessChallenge flags a page that showed an anti-bot check instead of content. domscout reports what loaded. Deciding whether it is malicious stays with you, and a page that shows data-centre visitors something different will show that.

Where it shows up

  • Triage of links reported to a security or abuse inbox.
  • Evidence of an impersonation page for a takedown request.
  • A picture of a link's destination in a moderation queue.

The request

POST /screenshot. The screenshot and Markdown work on every plan for 1 credit. diagnostics, for the redirect chain and contacted domains, starts at Pro and makes it 2. Add save: true to keep the capture on your plan's retention schedule as evidence.

cURL
curl -X POST https://api.domscout.io/screenshot \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://suspicious.example.net/verify",
    "responseType": "json",
    "extractMarkdown": true,
    "diagnostics": {
      "console": false,
      "pageErrors": false,
      "network": true,
      "resources": false,
      "timing": false,
      "maxEntries": 100
    }
  }'
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://suspicious.example.net/verify",
    responseType: "json",
    extractMarkdown: true,
    diagnostics: {
      console: false,
      pageErrors: false,
      network: true,
      resources: false,
      timing: false,
      maxEntries: 100
    }
  }),
});
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://suspicious.example.net/verify",
        "responseType": "json",
        "extractMarkdown": True,
        "diagnostics": {
            "console": False,
            "pageErrors": False,
            "network": True,
            "resources": False,
            "timing": False,
            "maxEntries": 100
        }
    },
)
print(response.json())
Go
package main

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

func main() {
	body, _ := json.Marshal(map[string]any{
		"url": "https://suspicious.example.net/verify",
		"responseType": "json",
		"extractMarkdown": true,
		"diagnostics": map[string]any{
			"console": false,
			"pageErrors": false,
			"network": true,
			"resources": false,
			"timing": false,
			"maxEntries": 100,
		},
	})
	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://suspicious.example.net/verify',
        'responseType' => 'json',
        'extractMarkdown' => true,
        'diagnostics' => [
            'console' => false,
            'pageErrors' => false,
            'network' => true,
            'resources' => false,
            'timing' => false,
            'maxEntries' => 100
        ]
    ]),
]);
$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://suspicious.example.net/verify",
    responseType: "json",
    extractMarkdown: true,
    diagnostics: {
      console: false,
      pageErrors: false,
      network: true,
      resources: false,
      timing: false,
      maxEntries: 100
    }
  }.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://suspicious.example.net/verify",
                "responseType": "json",
                "extractMarkdown": true,
                "diagnostics": {
                    "console": false,
                    "pageErrors": false,
                    "network": true,
                    "resources": false,
                    "timing": false,
                    "maxEntries": 100
                }
            }
            """;
        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://suspicious.example.net/verify",
    responseType = "json",
    extractMarkdown = true,
    diagnostics = new {
        console = false,
        pageErrors = false,
        network = true,
        resources = false,
        timing = false,
        maxEntries = 100
    }
});
Console.WriteLine(await response.Content.ReadAsStringAsync());

Go further

More in Security, evidence and compliance: Web archiving and evidence · Third-party script audit · Hacked site detection · Tracking silent edits · Marketing page records · All use cases

Give your product a browser.

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