# DomScan API documentation (full text) > Every DomScan documentation page in one Markdown file, in the same order as the docs navigation. The short index is https://domscan.net/llms.txt. Markdown versions of every docs page are available by appending .md to the page URL. Exact request and response schemas are in https://domscan.net/v1/openapi.json. Pages: 77 - https://domscan.net/docs.md - https://domscan.net/docs/authentication.md - https://domscan.net/docs/credits-pricing.md - https://domscan.net/docs/base-url.md - https://domscan.net/docs/quickstart.md - https://domscan.net/docs/request-headers.md - https://domscan.net/docs/ai-agents.md - https://domscan.net/docs/response-format.md - https://domscan.net/docs/status-codes.md - https://domscan.net/docs/error-codes.md - https://domscan.net/docs/rate-limits.md - https://domscan.net/docs/caching.md - https://domscan.net/docs/best-practices.md - https://domscan.net/docs/versioning.md - https://domscan.net/docs/products/web-scraping.md - https://domscan.net/docs/products/redirects.md - https://domscan.net/docs/products/technology-detection.md - https://domscan.net/docs/products/robots-txt.md - https://domscan.net/docs/products/sitemap-audit.md - https://domscan.net/docs/products/onpage.md - https://domscan.net/docs/products/javascript-seo.md - https://domscan.net/docs/products/structured-data.md - https://domscan.net/docs/products/keyword-density.md - https://domscan.net/docs/products/page-links.md - https://domscan.net/docs/products/hreflang.md - https://domscan.net/docs/products/robots-txt-tester.md - https://domscan.net/docs/products/ads-txt.md - https://domscan.net/docs/products/duplicate-content.md - https://domscan.net/docs/products/site-audit.md - https://domscan.net/docs/products/screenshot.md - https://domscan.net/docs/products/accessibility.md - https://domscan.net/docs/products/cookie-scan.md - https://domscan.net/docs/products/page-weight.md - https://domscan.net/docs/products/website-categorization.md - https://domscan.net/docs/products/url-intelligence.md - https://domscan.net/docs/products/name-availability.md - https://domscan.net/docs/products/domain-availability.md - https://domscan.net/docs/products/domain-discovery.md - https://domscan.net/docs/products/rdap-coverage.md - https://domscan.net/docs/products/domain-suggestions.md - https://domscan.net/docs/products/domain-valuation.md - https://domscan.net/docs/products/domain-health.md - https://domscan.net/docs/products/domain-lifecycle.md - https://domscan.net/docs/products/domain-compare.md - https://domscan.net/docs/products/tld-intelligence.md - https://domscan.net/docs/products/domain-pricing.md - https://domscan.net/docs/products/domain-score.md - https://domscan.net/docs/products/whois.md - https://domscan.net/docs/products/rdap.md - https://domscan.net/docs/products/domain-profile.md - https://domscan.net/docs/products/dns-lookup.md - https://domscan.net/docs/products/dns-security.md - https://domscan.net/docs/products/dns-propagation.md - https://domscan.net/docs/products/subdomains.md - https://domscan.net/docs/products/ip-intelligence.md - https://domscan.net/docs/products/mac-lookup.md - https://domscan.net/docs/products/domain-similarity.md - https://domscan.net/docs/products/typosquatting.md - https://domscan.net/docs/products/idn-analysis.md - https://domscan.net/docs/products/certificate-intelligence.md - https://domscan.net/docs/products/vulnerability-intelligence.md - https://domscan.net/docs/products/security-headers.md - https://domscan.net/docs/products/security-txt.md - https://domscan.net/docs/products/domain-reputation.md - https://domscan.net/docs/products/email-authentication.md - https://domscan.net/docs/products/email-compliance.md - https://domscan.net/docs/products/email-blacklist.md - https://domscan.net/docs/products/social-handles.md - https://domscan.net/docs/products/email-verification.md - https://domscan.net/docs/products/phone-validation.md - https://domscan.net/docs/products/company-lookup.md - https://domscan.net/docs/products/identity-assets.md - https://domscan.net/docs/products/identity-resolution.md - https://domscan.net/docs/products/watchlist.md - https://domscan.net/docs/products/brand-monitor.md - https://domscan.net/docs/products/batch-jobs.md - https://domscan.net/docs/products/workflow-recipes.md --- Source: https://domscan.net/docs # API Documentation Explore DomScan API endpoints, authentication, credits, request parameters, JSON responses, code examples, and integration guides. ## Overview DomScan provides a REST API for domain intelligence. Check availability across 1,100+ TLDs, get AI-powered name suggestions, estimate domain values, monitor domain health, detect typosquatting threats, and check social handle availability. ### Getting started [Authentication /docs/authentication](https://domscan.net/docs/authentication) [Quickstart /docs/quickstart](https://domscan.net/docs/quickstart) [Request headers /docs/request-headers](https://domscan.net/docs/request-headers) [Credits & pricing /docs/credits-pricing](https://domscan.net/docs/credits-pricing) ### Connect to your AI tool Install the DomScan MCP server in one click, or run one command in your terminal. Your tool asks you to sign in to DomScan the first time it runs a check. [Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=domscan&config=eyJ1cmwiOiJodHRwczovL2RvbXNjYW4ubmV0L21jcCJ9)[Add to VS Code](vscode:mcp/install?%7B%22name%22%3A%22domscan%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fdomscan.net%2Fmcp%22%7D)[Add to VS Code Insiders](vscode-insiders:mcp/install?%7B%22name%22%3A%22domscan%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fdomscan.net%2Fmcp%22%7D) Claude Code `claude mcp add --transport http domscan https://domscan.net/mcp` Codex `codex mcp add domscan --url https://domscan.net/mcp` Codex sign-in `codex mcp login domscan` These links and commands never contain your API key. Tools that support sign-in connect to your DomScan account directly. To use a key instead, replace `YOUR_API_KEY` with a key from [your API keys](https://domscan.net/api-keys). [Setup for every AI tool](https://domscan.net/docs/ai-agents) ### Web Data [Web Scraping /docs/products/web-scraping](https://domscan.net/docs/products/web-scraping) [Redirect Chain /docs/products/redirects](https://domscan.net/docs/products/redirects) [Tech Stack Detection /docs/products/technology-detection](https://domscan.net/docs/products/technology-detection) [Robots.txt API /docs/products/robots-txt](https://domscan.net/docs/products/robots-txt) [XML sitemap audit API /docs/products/sitemap-audit](https://domscan.net/docs/products/sitemap-audit) [On-page SEO audit API /docs/products/onpage](https://domscan.net/docs/products/onpage) [JavaScript SEO rendering check API /docs/products/javascript-seo](https://domscan.net/docs/products/javascript-seo) [Structured data validation API /docs/products/structured-data](https://domscan.net/docs/products/structured-data) [Keyword density API /docs/products/keyword-density](https://domscan.net/docs/products/keyword-density) [Page links and broken link checker API /docs/products/page-links](https://domscan.net/docs/products/page-links) [Hreflang validation API /docs/products/hreflang](https://domscan.net/docs/products/hreflang) [Robots.txt Tester API /docs/products/robots-txt-tester](https://domscan.net/docs/products/robots-txt-tester) [ads.txt and sellers.json validation API /docs/products/ads-txt](https://domscan.net/docs/products/ads-txt) [Duplicate content checker API /docs/products/duplicate-content](https://domscan.net/docs/products/duplicate-content) [Site audit and SEO crawler API /docs/products/site-audit](https://domscan.net/docs/products/site-audit) [Website screenshot API /docs/products/screenshot](https://domscan.net/docs/products/screenshot) [Accessibility audit API /docs/products/accessibility](https://domscan.net/docs/products/accessibility) [Cookie and tracker scanner API /docs/products/cookie-scan](https://domscan.net/docs/products/cookie-scan) [Page weight and resource API /docs/products/page-weight](https://domscan.net/docs/products/page-weight) [Website Categorization /docs/products/website-categorization](https://domscan.net/docs/products/website-categorization) [Unified URL Intelligence /docs/products/url-intelligence](https://domscan.net/docs/products/url-intelligence) ### Domain Intelligence [Name Availability API /docs/products/name-availability](https://domscan.net/docs/products/name-availability) [Check Domain Availability /docs/products/domain-availability](https://domscan.net/docs/products/domain-availability) [Domain Finder Recipe /docs/products/domain-discovery](https://domscan.net/docs/products/domain-discovery) [TLD Coverage /docs/products/rdap-coverage](https://domscan.net/docs/products/rdap-coverage) [Domain Suggestions /docs/products/domain-suggestions](https://domscan.net/docs/products/domain-suggestions) [Domain Valuation /docs/products/domain-valuation](https://domscan.net/docs/products/domain-valuation) [Domain Health /docs/products/domain-health](https://domscan.net/docs/products/domain-health) [Domain Lifecycle /docs/products/domain-lifecycle](https://domscan.net/docs/products/domain-lifecycle) [Domain Compare /docs/products/domain-compare](https://domscan.net/docs/products/domain-compare) [TLD Intelligence /docs/products/tld-intelligence](https://domscan.net/docs/products/tld-intelligence) [Domain Pricing /docs/products/domain-pricing](https://domscan.net/docs/products/domain-pricing) [Domain Score /docs/products/domain-score](https://domscan.net/docs/products/domain-score) [WHOIS Lookup /docs/products/whois](https://domscan.net/docs/products/whois) [RDAP Lookup /docs/products/rdap](https://domscan.net/docs/products/rdap) [Domain Profile /docs/products/domain-profile](https://domscan.net/docs/products/domain-profile) ### DNS & Infrastructure [DNS Lookup /docs/products/dns-lookup](https://domscan.net/docs/products/dns-lookup) [DNS Security Analysis /docs/products/dns-security](https://domscan.net/docs/products/dns-security) [DNS Resolver Comparison /docs/products/dns-propagation](https://domscan.net/docs/products/dns-propagation) [Subdomain Finder /docs/products/subdomains](https://domscan.net/docs/products/subdomains) [IP Geolocation /docs/products/ip-intelligence](https://domscan.net/docs/products/ip-intelligence) [MAC Address Lookup /docs/products/mac-lookup](https://domscan.net/docs/products/mac-lookup) ### Security & Trust [Domain Similarity /docs/products/domain-similarity](https://domscan.net/docs/products/domain-similarity) [Typosquatting Detection /docs/products/typosquatting](https://domscan.net/docs/products/typosquatting) [IDN and homograph analysis API /docs/products/idn-analysis](https://domscan.net/docs/products/idn-analysis) [SSL Certificates /docs/products/certificate-intelligence](https://domscan.net/docs/products/certificate-intelligence) [Website Vulnerability Scanner /docs/products/vulnerability-intelligence](https://domscan.net/docs/products/vulnerability-intelligence) [Security headers API /docs/products/security-headers](https://domscan.net/docs/products/security-headers) [security.txt API /docs/products/security-txt](https://domscan.net/docs/products/security-txt) [Domain Reputation /docs/products/domain-reputation](https://domscan.net/docs/products/domain-reputation) [Email Authentication /docs/products/email-authentication](https://domscan.net/docs/products/email-authentication) [Email Compliance /docs/products/email-compliance](https://domscan.net/docs/products/email-compliance) [Email Blacklist /docs/products/email-blacklist](https://domscan.net/docs/products/email-blacklist) ### Identity & Verification [Social Handle Availability /docs/products/social-handles](https://domscan.net/docs/products/social-handles) [Email Verification /docs/products/email-verification](https://domscan.net/docs/products/email-verification) [Phone Number Intelligence /docs/products/phone-validation](https://domscan.net/docs/products/phone-validation) [Company Lookup /docs/products/company-lookup](https://domscan.net/docs/products/company-lookup) [Website Identity Assets /docs/products/identity-assets](https://domscan.net/docs/products/identity-assets) [Internet Identity Resolution /docs/products/identity-resolution](https://domscan.net/docs/products/identity-resolution) ### Monitoring & Automation [Domain Watchlist /docs/products/watchlist](https://domscan.net/docs/products/watchlist) [Brand Monitor /docs/products/brand-monitor](https://domscan.net/docs/products/brand-monitor) [Asynchronous API batches /docs/products/batch-jobs](https://domscan.net/docs/products/batch-jobs) [Workflow recipes /docs/products/workflow-recipes](https://domscan.net/docs/products/workflow-recipes) **Start free:** DomScan includes 10,000 free credits per month. No credit card required. We'll give plenty of notice before any pricing changes. ## Resources ### Reference [Response format /docs/response-format](https://domscan.net/docs/response-format) [HTTP status codes /docs/status-codes](https://domscan.net/docs/status-codes) [Error codes /docs/error-codes](https://domscan.net/docs/error-codes) [Rate limits /docs/rate-limits](https://domscan.net/docs/rate-limits) [Caching /docs/caching](https://domscan.net/docs/caching) [Best practices /docs/best-practices](https://domscan.net/docs/best-practices) [Versioning /docs/versioning](https://domscan.net/docs/versioning) ### Links [Home /](https://domscan.net/) [APIs /apis](https://domscan.net/apis) [MCP Integration /mcp-domain-checker](https://domscan.net/mcp-domain-checker) [Live Coverage /v1/coverage](https://domscan.net/v1/coverage) [OpenAPI 3.0 /v1/openapi.json](https://domscan.net/v1/openapi.json) [Swagger 2.0 /v1/swagger.json](https://domscan.net/v1/swagger.json) [llms.txt /llms.txt](https://domscan.net/llms.txt) [Postman /v1/postman.json](https://domscan.net/v1/postman.json) [domscan-cli github.com/estevecastells/domscan-cli/releases/latest](https://github.com/estevecastells/domscan-cli/releases/latest) [SDK Hub github.com/estevecastells/domscan-sdk](https://github.com/estevecastells/domscan-sdk) [@domscan/sdk github.com/estevecastells/domscan-sdk/tree/main/node](https://github.com/estevecastells/domscan-sdk/tree/main/node) [domscan-sdk github.com/estevecastells/domscan-sdk/tree/main/python](https://github.com/estevecastells/domscan-sdk/tree/main/python) --- Source: https://domscan.net/docs/authentication # Authentication Sign up for free to get your API key and 10,000 credits per month. For programmatic access with better rate limits, manage your API key from the [dashboard](https://domscan.net/dashboard). Pass your API key via header: ```bash # X-API-Key header curl -H "X-API-Key: your-api-key" "https://domscan.net/v1/status?name=example&tlds=com" # Or Authorization header curl -H "Authorization: Bearer your-api-key" "https://domscan.net/v1/status?name=example&tlds=com" ``` --- Source: https://domscan.net/docs/credits-pricing # Credits & pricing DomScan API: DomScan includes 10,000 free credits per month. No credit card required. We'll give plenty of notice before any pricing changes. DomScan includes 10,000 free credits per month. No credit card required. We'll give plenty of notice before any pricing changes. Credits refresh monthly on signup anniversary. Need more credits? Purchase packs that never expire: ### Credits per endpoint Find common endpoint costs below. Some reference endpoints are free. For the complete, machine-readable rate card, use /v1/pricing. | Endpoint | Credits | Description | | --- | --- | --- | | `/v1/coverage` | 0 | List TLDs with RDAP mappings | | `/v1/tlds` | 0 | TLD metadata list | | `/v1/watchlist` | 1 | View your watchlist | | `/v1/webhooks` | 2 | Per alert delivered to your webhook endpoint. Failed deliveries are refunded and test events are free. | | `/v1/status` | 1 | Check domain availability | | `/v1/health/quick` | 1 | Quick health check | | `/v1/dns` | 1 | DNS lookup | | `/v1/dns/bulk` | 1/domain | Bulk DNS lookup (up to 25 domains) | | `/v1/ip` | 1 | IP geolocation | | `/v1/value` | 2 | Domain valuation | | `/v1/prices` | 0-1/pair | Registration prices | | `/v1/tlds/:tld` | 1 | TLD details | | `/v1/watchlist/check` | 1 | Check watchlist item | | `/v1/typos/permutations` | 1 | Typo permutations | | `/v1/typos/score` | 1 | Typo risk score | | `/v1/email/check` | 1 | Email blacklist check | | `/v1/status/bulk` | 1/domain | Check availability for multiple domain names at once. Supports up to 50 domains per request. | | `/v1/health` | 3 | Full health check | | `/v1/dns/all` | 2 | All DNS records | | `/v1/profile` | 3 | Domain profile | | `/v1/redirects` | 2 | Redirect chain | | `/v1/tech` | 3-9 | Tech stack detection | | `/v1/categorize` | 3 | Website categorization | | `/v1/similarity` | 2 | Domain similarity | | `/v1/typos` | 2-3 | Typosquatting detection | | `/v1/reputation` | 3 | Domain reputation | | `/v1/reputation/bulk` | 3/domain | Bulk domain reputation (up to 3 domains) | | `/v1/certificates` | 2 | SSL certificate | | `/v1/certificates/bulk` | 2/domain | SSL certificate | | `/v1/social` | 2 | Social handle check | | `/v1/social/bulk` | 2/handle | Bulk Social Handle Check | | `/v1/company` | 3 | Company lookup | | `/v1/suggest` | 2-5 | Domain suggestions | | `/v1/whois` | 3 | WHOIS lookup | | `/v1/whois/history` | 3 | WHOIS change history | | `/v1/whois/bulk` | 3/domain | Bulk WHOIS lookup (up to 20 domains) | | `/v1/rdap/bulk` | 2/query | WHOIS lookup | | `/v1/prices/bulk` | 1/pair | Bulk pricing | | `/v1/dns/security` | 3 | DNS security analysis | | `/v1/dns/propagation` | 2 | DNS resolver comparison | | `/v1/dns/propagation/bulk` | 2/domain | DNS resolver comparison | | `/v1/email-auth/bulk` | 3/domain | Email authentication | | `/v1/hosting/bulk` | 3/domain | Hosting detection | | `/v1/value/bulk` | 2/domain | Bulk valuation | | `/v1/health/bulk` | 3/domain | Bulk health check | | `/v1/subdomains` | 4-5 | Subdomain finder | | `/v1/subdomains/bulk` | 4-5/domain | Subdomain finder | | `/v1/report` | 5 | Comprehensive report (saves ~10 credits vs individual calls) | ### Credit enforcement When your credits reach zero, API requests that cost credits return HTTP 402 (Payment Required). Free browser-based tools are not affected. `HTTP 402 Payment Required` ```json { "error": { "code": "INSUFFICIENT_CREDITS", "message": "Insufficient credits. This endpoint costs 2 credits but you have 0.", "credits_remaining": 0, "credits_required": 2, "purchase_url": "https://domscan.net/billing" } } ``` Credits refresh monthly on signup anniversary. ### Credit response headers All authenticated API responses include an X-Credits-Remaining header showing your current credit balance after the request. `X-Credits-Remaining: 9500` Every authenticated /v1 response, including errors, carries these headers: - `X-Credits-Charged`: credits this request charged, net of any refund made in the same request (0 when nothing was charged). - `X-Credits-Remaining`: your balance after the request. It is left out in the rare case the balance is not already known. - `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`: your burst capacity, the requests you can still send immediately, and the Unix time in seconds when the capacity is fully refilled. - MCP over HTTP returns `X-Credits-Charged` and `X-Credits-Remaining` for the tool calls in each request. ### Estimate the cost before running Send the method, path, query and body of a request to `POST /v1/estimate` to get the credits it would charge, with a breakdown and notes. Nothing is executed and the estimate costs 0 credits. When the final charge depends on the outcome, the estimate is the maximum and a note explains why. POST /v1/estimate #### Request body | Parameter | Type | Description | | --- | --- | --- | | method required | string Allowed values `GET`, `POST`, `PUT`, `PATCH`, `DELETE` | HTTP method of the request to estimate. | | path required | string | Path of the request to estimate, for example `/v1/value/bulk`. A query string in the path is also read. | | query optional | object | Query parameters as an object. Arrays are joined with commas. | | body optional | any | JSON body the request would send. | #### Example request ```bash curl -X POST "https://domscan.net/v1/estimate" \ -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"method":"POST","path":"/v1/value/bulk","body":{"domains":["example.com","example.org"]}}' ``` #### Example response ```json { "credits": 2, "breakdown": [ { "component": "domains", "quantity": 2, "unit_credits": 1, "credits": 2 } ], "notes": ["Requests rejected with a 4xx status or failing with a 5xx status are refunded automatically."], "maximum": false, "rejected": false } ``` #### Response fields | Field | Type | | --- | --- | | `credits` | integer | | `breakdown[]` | object[] | | `breakdown[]` | object | | `breakdown[].component` | string | | `breakdown[].quantity` | integer | | `breakdown[].unit_credits` | number | | `breakdown[].credits` | integer | | `notes[]` | string[] | | `maximum` | boolean | | `rejected` | boolean | | `billing_model` | string | | `endpoint` | object | | `endpoint.method` | string | | `endpoint.path` | string | | `dry_run` | boolean | Bulk, compare, recipe and pricing endpoints also accept `dry_run=true`. The request is answered with HTTP 200 and the same estimate plus `"dry_run": true`, without running it or charging credits. ### Credit calculator Estimate your credit usage for bulk operations: Endpoint Number of API calls Total credits needed 100 That's 1.0 % of your free monthly credits Exceeds free tier by 0 credits ### Credit packs Need more credits? Purchase packs that never expire: | Pack | Price | Per credit | | --- | --- | --- | | 50,000 credits | €9 / £7.50 / ¥1,500 | €0.00018 | | 250,000 credits | €29 / £24 / ¥4,800 | €0.000116 | | 1,000,000 credits | €79 / £66 / ¥13,000 | €0.000079 | --- Source: https://domscan.net/docs/base-url # Base URL All API requests should be made to: All API requests should be made to: ```text https://domscan.net ``` --- Source: https://domscan.net/docs/quickstart # Quickstart DomScan API: Make your first availability check in seconds. These examples call the /v1/status endpoint and return availability across multiple TLDs. Make your first availability check in seconds. These examples call the `/v1/status` endpoint and return availability across multiple TLDs. **Try it** [Dashboard](https://domscan.net/dashboard) Your API key: ```json {} ``` ```bash curl -H "X-API-Key: your-api-key" "https://domscan.net/v1/status?name=launch&tlds=com,io,ai&prefer_cache=1" ``` ```bash npm install -g https://github.com/estevecastells/domscan-cli/releases/latest/download/domscan-cli.tgz export DOMSCAN_API_KEY=dsk_your_key_here domscan check-domain-availability --name launch --tlds com,io,ai --prefer-cache ``` ```javascript npm install https://github.com/estevecastells/domscan-sdk/releases/latest/download/domscan-sdk-node.tgz import { DomScan } from '@domscan/sdk'; const domscan = new DomScan(); const response = await domscan.availability.checkDomainAvailability( { name: 'launch', tlds: 'com,io,ai', prefer_cache: true }, { withResponse: true }, ); console.log(response.data.results); console.log(response.meta.requestId, response.meta.credits); ``` ```python pip install https://github.com/estevecastells/domscan-sdk/releases/latest/download/domscan-sdk-python.tar.gz from domscan import DomScan domscan = DomScan() response = domscan.availability.check_domain_availability( name="launch", tlds="com,io,ai", prefer_cache=True, _with_response=True, ) print(response.data["results"]) print(response.request_id, response.credits_charged) ``` ```go package main import ( "encoding/json" "fmt" "net/http" "os" ) func domscanGet(url string) (*http.Response, error) { request, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, err } request.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) return http.DefaultClient.Do(request) } func main() { url := "https://domscan.net/v1/status?name=launch&tlds=com,io,ai&prefer_cache=1" resp, err := domscanGet(url) if err != nil { panic(err) } defer resp.Body.Close() var payload map[string]any json.NewDecoder(resp.Body).Decode(&payload) fmt.Println(payload["results"]) } ``` ```ruby require 'net/http' require 'json' uri = URI("https://domscan.net/v1/status?name=launch&tlds=com,io,ai&prefer_cache=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(request) } data = JSON.parse(response.body) puts data["results"] ``` --- Source: https://domscan.net/docs/request-headers # Request headers All API requests require authentication. Sign up for free to get your API key and 10,000 monthly credits. - **Content-Type:** `application/json` (required for POST requests) - **Accept:** `application/json` (optional but recommended) - **X-API-Key:** Your API key (get one free at [/dashboard](https://domscan.net/dashboard)) - **Authorization:** `Bearer your-api-key` (alternative to X-API-Key) - **Idempotency-Key:** optional, on POST requests that charge credits. Retrying with the same key and an identical request within 24 hours returns the stored response with `Idempotent-Replayed: true` and charges nothing again. Reusing a key for a different request returns 422 `IDEMPOTENCY_KEY_REUSED`, and a duplicate sent while the first is still running returns 409 `IDEMPOTENCY_IN_PROGRESS`. Responses larger than 1 MiB and refunded errors are not stored, so a retry runs normally. Keys are 1 to 255 printable ASCII characters, such as a UUID. - **DomScan-Naming:** optional. `snake` returns every camelCase response key in snake_case, the same as `naming=snake`. When both are sent, the query parameter wins. See [snake_case keys](https://domscan.net/docs/response-format#naming). --- Source: https://domscan.net/docs/ai-agents # Use DomScan with AI agents Connect DomScan to Claude, ChatGPT, Cursor, VS Code, Codex and Windsurf over MCP, give coding agents the API rules they need, and start from ready-made prompts. ### MCP or REST API? #### Use MCP when the assistant decides Connect the MCP server when an assistant chooses which checks to run during a conversation. It finds the DomScan tools on its own, signs in with your account or an API key, and gets structured results with the same classification, credit costs and error codes as the API. #### Use REST when your code decides Call the REST API from code that runs without an assistant: scheduled jobs, bulk pipelines, backends and CI checks. When a coding agent writes code that ships in your product, have it call the REST API from the OpenAPI description. Many teams use both: MCP to explore and prototype in a chat or editor, and the REST API in the code the agent writes. Both use the same API key and credit balance. ### Connect to your AI tool Install the DomScan MCP server in one click, or run one command in your terminal. Your tool asks you to sign in to DomScan the first time it runs a check. [Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=domscan&config=eyJ1cmwiOiJodHRwczovL2RvbXNjYW4ubmV0L21jcCJ9)[Add to VS Code](vscode:mcp/install?%7B%22name%22%3A%22domscan%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fdomscan.net%2Fmcp%22%7D)[Add to VS Code Insiders](vscode-insiders:mcp/install?%7B%22name%22%3A%22domscan%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fdomscan.net%2Fmcp%22%7D) Claude Code Claude Code with an API key Codex Codex sign-in `codex mcp login domscan` ### Setup by tool Every tool connects to the same MCP server at `https://domscan.net/mcp`. Tools that support sign-in open a DomScan login the first time they run a check. The others send your API key in the X-API-Key header. #### Claude Code Run this in your terminal. Claude Code asks you to sign in the first time it uses DomScan. Add `--scope user` to make DomScan available in every project. Claude Code `claude mcp add --transport http domscan https://domscan.net/mcp` Claude Code with an API key `claude mcp add --transport http domscan https://domscan.net/mcp --header "X-API-Key: YOUR_API_KEY"` #### Cursor Use the Add to Cursor button above, or add this entry to `~/.cursor/mcp.json` for every project or `.cursor/mcp.json` for one project. mcp.json ```json { "mcpServers": { "domscan": { "url": "https://domscan.net/mcp" } } } ``` #### VS Code Use the Add to VS Code button above, or add this entry to `.vscode/mcp.json` in your workspace. VS Code asks you to sign in when the server starts. .vscode/mcp.json ```json { "servers": { "domscan": { "type": "http", "url": "https://domscan.net/mcp" } } } ``` #### Codex Add the server, then sign in. To use an API key instead, add this block to `~/.codex/config.toml` and set `DOMSCAN_API_KEY` in your environment. Codex `codex mcp add domscan --url https://domscan.net/mcp` Codex sign-in `codex mcp login domscan` ~/.codex/config.toml ```json [mcp_servers.domscan] url = "https://domscan.net/mcp" env_http_headers = { "X-API-Key" = "DOMSCAN_API_KEY" } ``` #### ChatGPT Turn on developer mode in ChatGPT under Settings, Connectors, Advanced. Then create a connector with this URL and choose OAuth. Step-by-step instructions are on the [MCP setup page](https://domscan.net/mcp-domain-checker). MCP server URL `https://domscan.net/mcp` #### Claude In Claude on the web or in Claude Desktop, open Settings, then Connectors, and add a custom connector named DomScan with this URL. Claude opens a DomScan sign-in to finish. MCP server URL `https://domscan.net/mcp` #### Windsurf Open the MCP settings in Windsurf, view the raw configuration and add this entry to `mcp_config.json`. Replace YOUR_API_KEY with your key. mcp_config.json ```json { "mcpServers": { "domscan": { "serverUrl": "https://domscan.net/mcp", "headers": { "X-API-Key": "YOUR_API_KEY" } } } } ``` These links and commands never contain your API key. Tools that support sign-in connect to your DomScan account directly. To use a key instead, replace `YOUR_API_KEY` with a key from [your API keys](https://domscan.net/api-keys). ### Instructions for coding agents Paste this into AGENTS.md, CLAUDE.md or your editor rules file so coding agents call DomScan correctly. AGENTS.md ```text ## DomScan API Use DomScan (https://domscan.net) for domain availability, DNS, WHOIS and RDAP, SSL, email security and valuation checks. - Base URL: `https://domscan.net`. Endpoints are under `/v1`. - Auth: send `X-API-Key: $DOMSCAN_API_KEY` (or `Authorization: Bearer $DOMSCAN_API_KEY`). Read the key from the environment. Never hardcode it, log it or put it in a URL. - Contract: read the OpenAPI description at https://domscan.net/v1/openapi.json before choosing an endpoint or parameter, and do not guess parameter names. A site summary for LLMs is at https://domscan.net/llms.txt. - MCP: the remote server is https://domscan.net/mcp (streamable HTTP, sign-in or the same API key headers). - Credits: most endpoints cost credits. Before bulk or repeated work, call `POST /v1/estimate` with the `method`, `path`, `query` and `body` of the request, or add `dry_run=true` to bulk, compare, recipe and pricing endpoints. Both are free. Track the `X-Credits-Charged` and `X-Credits-Remaining` response headers. - Bulk: check up to 50 full domain names with one `POST /v1/status/bulk` request instead of looping over single checks. - Retries: send an `Idempotency-Key` header (for example a UUID) on POST requests that charge credits. Retrying the same request with the same key within 24 hours returns the stored response without charging again. Retry only when `error.retryable` is true, and wait for `Retry-After` on 429. - Errors: every error body is `{"error": {"type", "code", "message", "status", "retryable", "request_id", ...}}`. Branch on `error.code`, such as `INVALID_PARAMETER`, `INSUFFICIENT_CREDITS` or `RATE_LIMITED`, not on the message. - Unknown is not absent: results include `classification.status` of `present`, `absent` or `unknown`. Treat `unknown` as "try again later", never as available or missing, and never treat absence as proof that a name can be registered or claimed. - Freshness: endpoints that can answer from recent data accept `max_age` in seconds (`max_age=0` asks for a fresh check) and return `cache_age_s`. It does not change the cost. - Smaller responses: add `fields=a,b.c` or `compact=true` to the query string. Neither changes the cost. - More: https://domscan.net/AGENTS.md and https://domscan.net/docs. ``` ### Prompts to try Copy a prompt or open it in your assistant. Connect DomScan first so the assistant can run the checks. 1. Using DomScan, check whether these 50 names are available as .com domains: [paste names]. First estimate the credit cost and show it to me before running anything. Then list available, taken and unknown results separately, and do not treat unknown results as available. 2. Use DomScan to audit the email security of example.com: SPF, DKIM, DMARC and blacklist status. Explain each problem in plain language and suggest the DNS record that fixes it. 3. I am thinking about buying example.com. Use DomScan to check its WHOIS and registration dates, DNS, SSL certificate, reputation and estimated value, then summarize the risks and what I should verify before paying. 4. Use DomScan to find lookalike and typosquatting domains of example.com that are already registered. Rank them by risk and point out any that have a website or mail server. 5. Add DomScan to this project. Read https://domscan.net/AGENTS.md and https://domscan.net/v1/openapi.json, then write a small typed client for POST /v1/status/bulk that reads DOMSCAN_API_KEY from the environment, sends an Idempotency-Key header and keeps unknown results separate from available ones. Add tests. ### Machine-readable resources Point agents at these public files instead of copying documentation into prompts. - [`/AGENTS.md`](https://domscan.net/AGENTS.md) Public agent guide - [`/llms.txt`](https://domscan.net/llms.txt) Site summary for LLMs - [`/v1/openapi.json`](https://domscan.net/v1/openapi.json) OpenAPI 3.0 - [`/mcp/tool-mapping.json`](https://domscan.net/mcp/tool-mapping.json) Old and new MCP tool names --- Source: https://domscan.net/docs/response-format # Response format DomScan API: All responses are JSON. Each domain result contains these common fields: All responses are JSON. Each domain result contains these common fields: - `domain` - Complete domain name - `available` - Boolean availability status - `source` - "rdap" or "cache" - `checked_at` - ISO 8601 timestamp - `error` - Present if an error occurred ### Response metadata Each API response includes a request ID and freshness value. When available, response headers also show credits requested, charged, refunded, and remaining, plus your rate-limit plan, limit, remaining capacity, and policy. A freshness value of `unknown` means freshness could not be established for that response. It does not mean the data is current. ### Field selection and compact responses Add `fields` or `compact` to the query string of any GET or POST request to receive a smaller JSON response. Both are optional. On POST requests they go in the query string, not the body. Neither changes the credit cost. #### Select fields `fields` takes comma-separated dot paths, such as `fields=domain,classification.status,records.data`. When a path crosses a list, it applies to every item. Items keep their position, and an item without any selected field becomes `{}`. A null value along a path is kept as null. Send up to 50 paths, each with up to 6 segments of 1 to 64 letters, digits or underscores. Any other value returns 400 INVALID_PARAMETER before the request runs, so nothing is charged. Paths that match nothing in the response are left out and listed in the `X-Fields-Ignored` response header, up to 20 paths. #### Compact responses `compact=true` removes only the following, and only at the top level of the response: - In the `meta` object: `served_by` and the timing keys `duration_ms`, `query_time_ms`, `total_ms`, `total_time_ms`, `latency_ms`, `generation_ms` and `check_duration_ms`. The `meta` object itself is removed when nothing else is left in it. - `warnings`, `caveats`, `notes` and `errors` when they are empty lists. - `request_id` when it repeats the `X-Request-Id` header. Data fields, `classification`, nested objects and list items are never removed. When both parameters are sent, compact runs first and fields second. Only successful JSON responses are reshaped. Error responses, CSV, text and streamed responses, and `dry_run` estimates are returned unchanged. Reshaped responses are sent without indentation. With an `Idempotency-Key`, `fields` and `compact` are part of the request. A retry with the same values returns the stored, reshaped response. Reusing the key with different values returns 422 IDEMPOTENCY_KEY_REUSED. MCP tools accept the same optional `fields` and `compact` arguments. Unmatched paths are listed in `_meta.fields_ignored` on the tool result. #### Example ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns?domain=google.com&type=TXT&fields=domain,status,records.data,records.ttl,owner&compact=true" X-Fields-Ignored: owner { "domain": "google.com", "records": [ { "data": "v=spf1 include:_spf.google.com ~all", "ttl": 300 }, { "data": "google-site-verification=abc123", "ttl": 300 } ], "status": "success" } ``` ### snake_case keys (naming) Most response keys are already snake_case, but a few endpoints return some camelCase keys, such as `registrarName` in pricing results, `tldTier` in valuation factors and `eventDate` in RDAP events. Add `naming=snake` to the query string, or send the `DomScan-Naming: snake` header, to receive every one of those keys in snake_case. Without it, responses keep their current keys. A key changes only when it starts with a lowercase letter, contains only letters and digits and has at least one capital letter. Each new word gets an underscore and the key is lowercased. Acronyms stay together, including `IPv4` and plurals such as `IPs`: `registrarName` becomes `registrar_name`, `secureDNS` becomes `secure_dns`, `ipv4Address` becomes `ipv4_address` and `nameserverIPs` becomes `nameserver_ips`. Keys that are data rather than field names keep their exact spelling, for example DNS record types such as `A` and `MX`, grades such as `A+`, domain names, header names and technology names. Values are never changed, and nested objects and lists are converted at every level. If an object already has the snake_case name, for example both `fooBar` and `foo_bar`, `foo_bar` keeps its value and `fooBar` keeps its original name, so nothing is lost. Key order does not change. The query parameter wins over the header, so `naming=default` turns a header opt-in off for one request. Accepted values are `snake` and `default`. Any other value returns 400 INVALID_PARAMETER before the request runs, so nothing is charged. Responses include `Vary: DomScan-Naming`. `naming` runs before `compact` and `fields`, so write `fields` paths in snake_case, such as `fields=factors.tld_tier`. Error responses are already snake_case and never change, and the credit cost is the same. With an `Idempotency-Key`, the naming choice is part of the request whether it comes from the parameter or the header, so a retry returns the same keys. MCP tools accept the same optional `naming` argument. MCP calls do not read the header. ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" -H "DomScan-Naming: snake" "https://domscan.net/v1/value?domain=example.com&fields=domain,factors.tld_tier,factors.has_hyphens" { "domain": "example.com", "factors": { "tld_tier": "premium", "has_hyphens": false } } ``` ### Freshness control (max_age) Endpoints that can answer from recently checked data accept `max_age`, a whole number of seconds from 0 to 2592000 (30 days). Data older than `max_age` is checked again before it is returned, and `max_age=0` always checks fresh. Without `max_age`, each endpoint keeps its usual behavior. Every successful response from these endpoints includes a top-level `cache_age_s`: the age in seconds of the data used, or 0 when it was checked fresh. The same value is sent in the `X-Cache-Age` response header. When a response holds several items, such as an availability check for several domains, it is the age of the oldest item, and items keep their own `cache_age_s` where they already had one. `max_age` never changes how a result is classified. A result that could not be confirmed stays `unknown` however recent it is, and recent data is never shown as present or absent unless the original check confirmed it. `max_age` does not change what a request costs. A fresh check and an answer from recent data cost the same credits. On `/v1/status` and `/v1/status/bulk`, forced fresh checks (`max_age=0`) are limited per client to protect registries. Beyond that limit the request is answered as if `max_age` were not sent, and `cache_age_s` shows the age of what you received. A `max_age` that is not a whole number from 0 to 2592000 returns 400 INVALID_PARAMETER before the request runs, so nothing is charged. Endpoints that accept `max_age`: `GET /v1/status`, `POST /v1/status/bulk`, `GET /v1/subdomains`, `GET /v1/certificates`, `GET /v1/tech`, `GET /v1/categorize`, `GET /v1/identity-assets`, `GET /v1/identity-resolution`, `GET /v1/url-intelligence`, `GET /v1/agent-readiness`, `GET /v1/robots`, `GET /v1/ssl/deep-scan` #### Older cache parameters These parameters keep working and are now deprecated aliases of `max_age`. When you also send `max_age`, `max_age` wins. | Parameter | Endpoints | Same as | | --- | --- | --- | | `prefer_cache` | `/v1/status`, `/v1/subdomains` | `max_age=2592000` | | `skip_cache` | `/v1/status`, `/v1/tech`, `/v1/categorize`, `/v1/identity-assets`, `/v1/identity-resolution`, `/v1/url-intelligence`, `/v1/agent-readiness`, `/v1/robots` | `max_age=0` | | `cache_skip` | `/v1/status` | `max_age=0` | | `cache-skip` | `/v1/status` | `max_age=0` | | `options.prefer_cache (body)` | `/v1/status/bulk` | `max_age=2592000` | | `prefer_cache (body)` | `/v1/status/bulk` | `max_age=2592000` | | `options.skip_cache (body)` | `/v1/status/bulk` | `max_age=0` | | `options.cache_skip (body)` | `/v1/status/bulk` | `max_age=0` | | `options.cache-skip (body)` | `/v1/status/bulk` | `max_age=0` | | `refresh` | `/v1/ssl/deep-scan` | `max_age=0` | On `/v1/subdomains`, `prefer_cache` also keeps its cache-only behavior: when nothing is stored yet, the request returns 202 without charging and starts the lookup in the background. MCP tools for these endpoints accept the same optional `max_age` argument, and their results include `cache_age_s`. ### Pagination (limit and cursor) Endpoints that return long lists accept `limit` and `cursor`, and every response includes `has_more` and `next_cursor`. To get the next page, repeat the request with `cursor` set to `next_cursor`. On the last page `has_more` is false and `next_cursor` is null. Without `limit`, each endpoint returns the same number of items as before, so existing requests are unchanged. You can change `limit` from one page to the next. Cursors are opaque and signed. A cursor only works for the account that received it and for the same query, such as the same domain and filters. A cursor that was edited, belongs to another account or is sent with different filters returns 400 INVALID_CURSOR. Pages follow a stable order, so items added or removed between requests are not repeated or skipped. On the history endpoints, summary fields describe the items on the current page. Each page is a normal request and costs the endpoint's usual credits, exactly as a request with `limit` did before. Free endpoints stay free. Older parameters keep working: `offset` on `/v1/email/blacklist`, and the numeric `pagination.next_cursor` on `/v1/certificates`. | Endpoint | Default page size | Maximum limit | | --- | --- | --- | | `GET /v1/whois/history` | 50 | 100 | | `GET /v1/dns/history` | 100 | 1000 | | `GET /v1/subdomains` | 500 | 2000 | | `GET /v1/certificates` | 100 | 1000 | | `GET /v1/watchlist` | Whole list | 100 | | `GET /v1/watchlist/expiring` | Whole list | 100 | | `GET /v1/watchlist/available` | Whole list | 100 | | `GET /v1/brand-monitor` | Whole list | 100 | | `GET /v1/email/blacklist` | 1000 | 10000 | #### Example ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/whois/history?domain=example.com&limit=20" { "domain": "example.com", "snapshots": [ "..." ], "has_more": true, "next_cursor": "eyJvIjoi..." } curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/whois/history?domain=example.com&limit=20&cursor=eyJvIjoi..." ``` ### Classification status Endpoints that report whether something exists (domain registration, social handles, DNS and email authentication records, security.txt, robots.txt, sitemaps, security headers, parking, typosquat registrations and SSL certificates) add a `classification` object next to their existing fields. Existing fields keep their names and meaning. - `status` - `present`, `absent` or `unknown`. Present and absent are returned only when the check produced exact, authoritative evidence. - `reason` - Returned only when the status is `unknown`. Explains why no definite answer was possible. - `evidence` - Where the answer came from: `source`, `method`, `observed_at` and an optional `detail` such as `http_404` or `nxdomain`. - `checked_at` - When DomScan produced the classification. For cached results, `evidence.observed_at` is earlier. #### Unknown reasons - `blocked` - The target refused access, for example with HTTP 401, 403 or a bot challenge. - `rate_limited` - The target or registry asked us to slow down, for example with HTTP 429. - `timeout` - The check did not finish within its time budget. - `ambiguous` - A response arrived but did not prove presence or absence, for example an unexpected status code or a malformed record. - `upstream_error` - The data source failed, for example a DNS server failure or an HTTP 5xx response. - `unsupported` - This check is not available for the input, for example an unsupported TLD or a platform without a reliable checker. ```json { "classification": { "status": "unknown", "reason": "rate_limited", "evidence": { "source": "rdap", "method": "rdap_lookup", "observed_at": "2026-10-10T09:30:00.000Z", "detail": "http_429" }, "checked_at": "2026-10-10T09:30:00.000Z" } } ``` A blocked, rate-limited, timed-out or failed check is never reported as absent. Treat `unknown` as "try again later" rather than "not there", and never read absence as proof that a name can be claimed. #### Scores and grades with unknown checks Scores never count an unknown check as missing. The DNS security score and the email authentication grade leave unknown checks out, report them in `checks_unknown` and set `score_confidence` to `partial`. When every check is unknown, the score and grade are `null`. The SSL grade and score are `null` with `grade_reason` set to `certificate_not_retrieved` when no certificate could be read, and the reputation score reports unknown parking as `null` instead of not parked. --- Source: https://domscan.net/docs/status-codes # HTTP status codes Explore HTTP status codes API documentation, request parameters, response fields, code examples, and error handling for DomScan integrations. These are the HTTP status codes to handle, so you can tell apart successful responses, auth issues, credits, rate limits, missing data, and upstream failures. 200 **OK** Request successful 201 **Created** Resource created successfully. 400 **Bad Request** Invalid parameters 401 **Unauthorized** Missing or invalid API key/session. 402 **Payment Required** Not enough credits to run this request. 403 **Forbidden** Authenticated but not allowed to use this operation or mode. 404 **Not Found** Requested resource or data was not found. 429 **Too Many Requests** Rate limit exceeded 500 **Server Error** Internal error 502 **Bad Gateway** Upstream RDAP error 503 **Service Unavailable** Upstream service unavailable or temporarily rate limited. 504 **Gateway Timeout** Upstream lookup timed out. --- Source: https://domscan.net/docs/error-codes # Error codes Explore Error codes API documentation, request parameters, response fields, code examples, and error handling for DomScan integrations. ### Structured errors Every API error returns the same JSON shape: an `error` object with a stable `code`, a readable `message`, its `type` and HTTP `status`, whether it is `retryable`, the `request_id` and a `docs_url`. The `request_id` always matches the `X-Request-Id` response header, so include it when you contact support. ```json { "error": { "code": "INVALID_DOMAIN", "message": "Invalid domain format", "suggestion": "Use a registrable domain such as example.com", "type": "validation_error", "status": 400, "retryable": false, "request_id": "m5x7k2p-a9f3", "docs_url": "https://domscan.net/docs/check-availability" } } ``` ### Error fields | Field | Description | | --- | --- | | `code` | Stable machine-readable error code. Codes are never renamed, so you can safely branch on them. | | `message` | Readable explanation of the error. The wording can change, so do not parse it. | | `type` | Broad error category, such as `validation_error`, `authentication_error` or `rate_limit_error`. | | `status` | The HTTP status code, repeated in the body for logs and queues. | | `retryable` | Whether the same request can succeed if you retry it later. | | `request_id` | Unique request identifier. Matches the `X-Request-Id` header. | | `docs_url` | Link to the documentation section that explains this error. | | `suggestion` | Optional hint on how to fix the request. | | `details` | Optional structured context, such as the allowed methods or the invalid parameter. | | `retry_after` | Optional number of seconds to wait before retrying. Also sent as the `Retry-After` header. | ### Common error codes These are the codes most clients need to handle. Some endpoints return more specific codes that follow the same rules; the full list with status, type and retry behavior is in the OpenAPI specification under `x-domscan-error-codes`. `RATE_LIMIT_EXCEEDED` is still accepted as an alias of `RATE_LIMITED`. | Code | HTTP status | Type | Retryable | Description | | --- | --- | --- | --- | --- | | `BAD_REQUEST` | 400 | `validation_error` | No | Missing or invalid parameters | | `MISSING_PARAMETER` | 400 | `validation_error` | No | A required parameter is missing | | `INVALID_PARAMETER` | 400 | `validation_error` | No | A parameter has an invalid value | | `INVALID_JSON` | 400 | `validation_error` | No | The request body is not valid JSON | | `INVALID_DOMAIN` | 400 | `validation_error` | No | Invalid domain format | | `UNSUPPORTED_TLD` | 400 | `validation_error` | No | TLD not supported | | `SUBDOMAIN_NOT_SUPPORTED` | 400 | `validation_error` | No | This endpoint accepts registrable domains, not subdomains | | `VALIDATION_ERROR` | 422 | `validation_error` | No | The request is well formed but cannot be processed | | `AUTH_REQUIRED` | 401 | `authentication_error` | No | No API key or session was provided | | `INVALID_API_KEY` | 401 | `authentication_error` | No | The API key is invalid or has been revoked | | `INSUFFICIENT_CREDITS` | 402 | `credits_error` | No | Your account does not have enough credits for this request | | `FORBIDDEN` | 403 | `permission_error` | No | You do not have permission for this action | | `NOT_FOUND` | 404 | `not_found_error` | No | The endpoint or resource does not exist | | `METHOD_NOT_ALLOWED` | 405 | `request_error` | No | The endpoint exists but does not accept this HTTP method. The `Allow` header lists supported methods. | | `CONFLICT` | 409 | `conflict_error` | No | The request conflicts with the current state of the resource | | `IDEMPOTENCY_CONFLICT` | 409 | `conflict_error` | No | The idempotency key was already used with a different request | | `IDEMPOTENCY_KEY_REUSED` | 422 | `validation_error` | No | This `Idempotency-Key` was already used with a different request in the last 24 hours. Use a new key for a new request. | | `IDEMPOTENCY_IN_PROGRESS` | 409 | `conflict_error` | Yes | A request with this `Idempotency-Key` is still running. Retry after a moment to receive its stored response. | | `RATE_LIMITED` | 429 | `rate_limit_error` | Yes | Too many requests | | `INTERNAL` | 500 | `api_error` | No | Unexpected server error. Contact support with the request ID if it persists. | | `UPSTREAM_ERROR` | 502 | `upstream_error` | Yes | An upstream source returned an unusable response | | `UPSTREAM_UNAVAILABLE` | 503 | `upstream_error` | Yes | An upstream source is temporarily unavailable | | `SERVICE_UNAVAILABLE` | 503 | `upstream_error` | Yes | The service is temporarily unavailable | | `TIMEOUT` | 504 | `timeout_error` | Yes | An upstream source or registry did not respond in time | ### Retry guidance - Retry only when `retryable` is `true`. For validation, authentication and permission errors, fix the request first. - When `retry_after` or the `Retry-After` header is present, wait at least that many seconds before the next attempt. - Otherwise use exponential backoff with jitter, for example 1, 2, 4 and 8 seconds, and stop after a few attempts. - For batch and job creation, send an `Idempotency-Key` header so a retried request never creates a duplicate job. - For other POST requests that charge credits, an `Idempotency-Key` header makes a retry return the stored response instead of charging again. ### Compatibility Since 10 October 2026 every endpoint uses this format. Fields that some endpoints already returned, such as `credits_remaining`, `purchase_url`, `login_url`, `success` or `meta`, are kept during a compatibility period, so existing integrations keep working. Read error details from the `error` object in new code. --- Source: https://domscan.net/docs/rate-limits # Rate limits DomScan API: Authenticated responses also carry X-RateLimit-Reset , the Unix time in seconds when your burst capacity is fully refilled. - **Free accounts:** 120 requests per minute, with a burst of 60. This budget is shared by every API key and dashboard session on the account. - **Paid accounts:** 600 requests per minute, with a burst of 120. Counted per API key, or per IP for dashboard sessions. - **Bulk endpoints on free accounts:** An additional 20 requests per minute per account, and 100 per minute per network. - **Cached requests (prefer_cache=1):** Still counted against your rate limit, but they respond faster and skip the upstream lookup. - **Bulk endpoint:** 50 domains per request - **TLDs per request:** 50 maximum Exceeding a limit returns HTTP 429 with a `Retry-After` header. Every authenticated response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Policy`, so you can track your remaining budget instead of guessing. Authenticated responses also carry `X-RateLimit-Reset`, the Unix time in seconds when your burst capacity is fully refilled. --- Source: https://domscan.net/docs/caching # Caching DomScan API: DomScan caches responses for speed: DomScan caches responses for speed: - **Available domains:** 60 seconds - **Registered domains:** 6 hours --- Source: https://domscan.net/docs/best-practices # Best practices DomScan API: Add prefer_cache=1 to all requests unless you specifically need fresh data. #### 1. Always use caching Add `prefer_cache=1` to all requests unless you specifically need fresh data. #### 2. Batch your requests Use the bulk endpoint instead of making multiple individual requests. #### 3. Check coverage first Inspect RDAP endpoint mappings: `GET /v1/coverage`. This is not a complete lookup-support list; some TLDs use traditional WHOIS fallback. #### 4. Handle errors gracefully Implement retry logic with exponential backoff for transient failures. **Need help?** Contact us at [@estevecastells](https://x.com/estevecastells) --- Source: https://domscan.net/docs/versioning # Versioning and deprecations The API version is part of the path, for example /v1/status . Within a version, existing requests keep working. The API version is part of the path, for example `/v1/status`. Within a version, existing requests keep working. This page explains what can change, how much notice you get and how to find requests that need updating. ### Changes without notice New endpoints, optional parameters, response fields, values in existing lists of options, response headers and error codes can be added at any time. Write clients that ignore fields they do not know and handle new values gracefully. ### Breaking changes Removing or renaming an endpoint, parameter or field, or changing what it means, happens only after at least 12 months of notice. During that time the old form keeps working, responses to requests that use it carry `Deprecation` and `Sunset` headers, and the change is listed in the changelog. ### Response key naming Most response keys are snake_case. To receive every key in snake_case, add `naming=snake` or send the `DomScan-Naming: snake` header. This is opt-in, so the default responses do not change. See [snake_case keys](https://domscan.net/docs/response-format#naming). ### Deprecated aliases These older parameters still work. Each one keeps working until at least its sunset date. Move to the replacement before then. | Parameter | Endpoint | Use instead | Deprecated | Sunset | | --- | --- | --- | --- | --- | | `prefer_cache` | `GET /v1/status` | `max_age=2592000` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/status` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `cache_skip` | `GET /v1/status` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `cache-skip` | `GET /v1/status` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `options.prefer_cache` (JSON body) | `POST /v1/status/bulk` | `max_age=2592000` | 2026-10-10 | 2027-10-10 | | `prefer_cache` (JSON body) | `POST /v1/status/bulk` | `max_age=2592000` | 2026-10-10 | 2027-10-10 | | `options.skip_cache` (JSON body) | `POST /v1/status/bulk` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `options.cache_skip` (JSON body) | `POST /v1/status/bulk` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `options.cache-skip` (JSON body) | `POST /v1/status/bulk` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `prefer_cache` | `GET /v1/subdomains` | `max_age=2592000` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/tech` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/categorize` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/identity-assets` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/identity-resolution` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/url-intelligence` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/agent-readiness` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `skip_cache` | `GET /v1/robots` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `refresh` | `GET /v1/ssl/deep-scan` | `max_age=0` | 2026-10-10 | 2027-10-10 | | `cursor` (numeric value) | `GET /v1/certificates` | `cursor=` | 2026-10-10 | 2027-10-10 | | `offset` | `GET /v1/email/blacklist` | `cursor=` | 2026-10-10 | 2027-10-10 | ### Detecting deprecations A request that uses a deprecated alias receives these response headers. The response body stays the same. - `Deprecation`: the date the alias was deprecated, as `@` followed by Unix seconds (RFC 9745). - `Sunset`: the earliest date the alias may stop working (RFC 8594). - `Link`: a link to this page with `rel="deprecation"`. ```bash curl -i -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/status?name=example&tlds=com&skip_cache=true" Deprecation: @1791590400 Sunset: Sun, 10 Oct 2027 00:00:00 GMT Link: ; rel="deprecation"; type="text/html" ``` Browsers can read all three headers. Log them or alert on `Deprecation` to find code that needs updating before the sunset date. Every deprecation is also announced in the [API changelog](https://domscan.net/changelog). --- Source: https://domscan.net/docs/products/web-scraping # Web Scraping API Fetch public web pages as HTML, Markdown, or text with synchronous and asynchronous options. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/scrape-api) ## Operations POST `/v1/scrape` [View API reference](https://domscan.net/docs/products/web-scraping#scrapePage) POST `/v1/scrape/jobs` [View API reference](https://domscan.net/docs/products/web-scraping#createScrapeJob) GET `/v1/scrape/jobs/:job_id` [View API reference](https://domscan.net/docs/products/web-scraping#getScrapeJob) GET `/v1/scrape/jobs/:job_id/results` [View API reference](https://domscan.net/docs/products/web-scraping#getScrapeJobResults) ## POST `/v1/scrape` Operation: `scrapePage` Credits and authentication: 1-20 Authentication required POST /v1/scrape Credits: 1-20/item #### Body parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | mode | string Allowed values `standard`, `resilient`, `rendered`, `rendered_resilient` Default `standard` | optional | | output | string Allowed values `html`, `text`, `markdown` Default `html` | optional | #### Response fields | Field | Type | | --- | --- | | `data` | object | | `data.url` | string | | `data.final_url` | string | | `data.status` | integer \| null | | `data.outcome` | string | | `data.content_type` | string \| null | | `data.content` | string | | `data.bytes` | integer | | `data.truncated` | boolean | | `data.redirect_count` | integer | | `data.attempt_count` | integer | | `data.duration_ms` | integer | | `data.fetched_at` | string | | `data.headers` | object | | `data.rendered` | boolean | | `billing` | object | | `billing.credits_charged` | integer | | `billing.credits_refunded` | integer | | `billing.credits_per_item` | integer | | `billing.credits_net` | integer | | `billing.policy` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/scrape" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "url": "https://example.com/", "mode": "standard", "output": "markdown" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/scrape", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "url": "https://example.com/", "mode": "standard", "output": "markdown" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/scrape", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "url": "https://example.com/", "mode": "standard", "output": "markdown", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "url": "https://example.com/", "mode": "standard", "output": "markdown" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/scrape", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/scrape") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "url" => "https://example.com/", "mode" => "standard", "output" => "markdown" }) #### Example response ```json { "data": { "url": "https://example.com", "final_url": "https://example.com", "status": 1, "outcome": "success", "content_type": "domain", "content": "example", "bytes": 1, "truncated": false, "redirect_count": 1, "attempt_count": 1, "duration_ms": 1, "fetched_at": "2026-08-27T12:00:00Z", "headers": {}, "rendered": false }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_per_item": 1, "credits_net": 1, "policy": "effort_based" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `403` Forbidden - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests - `503` Service Unavailable ## POST `/v1/scrape/jobs` Operation: `createScrapeJob` Credits and authentication: 1-20 Authentication required POST /v1/scrape/jobs Credits: 1-20/item #### Body parameters | Parameter | Type | required | | --- | --- | --- | | notify_webhook | unknown | optional | | mode | string Allowed values `standard`, `resilient`, `rendered`, `rendered_resilient` Default `standard` | optional | | output | string Allowed values `html`, `text`, `markdown` Default `html` | optional | | urls | unknown[] | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.output` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_per_item` | integer | | `job.billing.credits_net` | integer | | `job.billing.policy` | string | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | | `idempotent_replay` | boolean | #### Example request ```bash curl -X POST "https://domscan.net/v1/scrape/jobs" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "mode": "resilient", "output": "text", "urls": [ "https://example.com/", { "url": "https://example.org/", "reference": "page-2" } ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/scrape/jobs", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "mode": "resilient", "output": "text", "urls": [ "https://example.com/", { "url": "https://example.org/", "reference": "page-2" } ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/scrape/jobs", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "mode": "resilient", "output": "text", "urls": [ "https://example.com/", { "url": "https://example.org/", "reference": "page-2", }, ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "mode": "resilient", "output": "text", "urls": [ "https://example.com/", { "url": "https://example.org/", "reference": "page-2" } ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/scrape/jobs", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/scrape/jobs") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "mode" => "resilient", "output" => "text", "urls" => [ "https://example.com/", { "url" => "https://example.org/", "reference" => "page-2" } ] }) #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "standard", "output": "html", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_per_item": 1, "credits_net": 1, "policy": "effort_based" }, "status_url": "https://example.com", "results_url": "https://example.com", "poll_after_ms": 1, "created_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z" }, "idempotent_replay": false } ``` #### HTTP status codes - `202` Accepted - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `403` Forbidden - `409` HTTP 409 - `429` Too Many Requests - `503` Service Unavailable ## GET `/v1/scrape/jobs/:job_id` Operation: `getScrapeJob` Credits and authentication: Free Authentication required GET /v1/scrape/jobs/:job_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.output` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_per_item` | integer | | `job.billing.credits_net` | integer | | `job.billing.policy` | string | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/scrape/jobs/example" ``` ```javascript const response = await fetch("https://domscan.net/v1/scrape/jobs/example", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/scrape/jobs/example", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/scrape/jobs/example", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/scrape/jobs/example") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "standard", "output": "html", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_per_item": 1, "credits_net": 1, "policy": "effort_based" }, "status_url": "https://example.com", "results_url": "https://example.com", "poll_after_ms": 1, "created_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/scrape/jobs/:job_id/results` Operation: `getScrapeJobResults` Credits and authentication: Free Authentication required GET /v1/scrape/jobs/:job_id/results Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | | limit | integer Default `20` | optional | | offset | integer Default `0` | optional | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.output` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_per_item` | integer | | `job.billing.credits_net` | integer | | `job.billing.policy` | string | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | | `results[]` | object[] | | `results[]` | object | | `results[].index` | integer | | `results[].url` | string | | `results[].reference` | string | | `results[].status` | string | | `results[].data` | object | | `results[].data.url` | string | | `results[].data.final_url` | string | | `results[].data.status` | integer \| null | | `results[].data.outcome` | string | | `results[].data.content_type` | string \| null | | `results[].data.content` | string | | `results[].data.bytes` | integer | | `results[].data.truncated` | boolean | | `results[].data.redirect_count` | integer | | `results[].data.attempt_count` | integer | | `results[].data.duration_ms` | integer | | `results[].data.fetched_at` | string | | `results[].data.headers` | object | | `results[].data.rendered` | boolean | | `results[].billing` | object | | `results[].billing.credits_charged` | integer | | `results[].billing.credits_refunded` | integer | | `results[].billing.credits_per_item` | integer | | `results[].billing.credits_net` | integer | | `results[].billing.policy` | string | | `pagination` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/scrape/jobs/example/results?limit=25&offset=0" ``` ```javascript const response = await fetch("https://domscan.net/v1/scrape/jobs/example/results?limit=25&offset=0", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/scrape/jobs/example/results?limit=25&offset=0", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/scrape/jobs/example/results?limit=25&offset=0", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/scrape/jobs/example/results?limit=25&offset=0") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "standard", "output": "html", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_per_item": 1, "credits_net": 1, "policy": "effort_based" }, "status_url": "https://example.com", "results_url": "https://example.com", "poll_after_ms": 1, "created_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z" }, "results": [ { "index": 1, "url": "https://example.com", "reference": "example", "status": "pending", "data": { "url": "https://example.com", "final_url": "https://example.com", "status": 1, "outcome": "success", "content_type": "domain", "content": "example", "bytes": 1, "truncated": false, "redirect_count": 1, "attempt_count": 1, "duration_ms": 1, "fetched_at": "2026-08-27T12:00:00Z", "headers": {}, "rendered": false }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_per_item": 1, "credits_net": 1, "policy": "effort_based" } } ], "pagination": {} } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `410` HTTP 410 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/redirects # Redirect Chain API Trace the full redirect chain for a URL. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/redirect-chain-api) ## Operations GET `/v1/redirects` [View API reference](https://domscan.net/docs/products/redirects#getRedirects) ## GET `/v1/redirects` Operation: `getRedirects` Credits and authentication: 2 Authentication required GET /v1/redirects Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `original_url` | string | | `final_url` | string | | `redirect_count` | integer | | `hops[]` | object[] | | `hops[]` | object | | `hops[].url` | string | | `hops[].status_code` | integer | | `hops[].location` | string | | `hops[].server` | string | | `hops[].content_type` | string | | `https_upgrade` | boolean | | `domain_changed` | boolean | | `final_status` | integer | | `final_title` | string | | `risk_summary` | object | | `risk_summary.risk_level` | string | | `risk_summary.risk_flags[]` | string[] | | `risk_summary.hop_count` | integer | | `risk_summary.redirect_count` | integer | | `risk_summary.https_upgrade` | boolean | | `risk_summary.https_downgrade` | boolean | | `risk_summary.domain_changed` | boolean | | `risk_summary.final_status` | integer | | `risk_summary.error_present` | boolean | | `risk_summary.tracking_parameter_hops` | integer | | `total_time_ms` | integer | | `checked_at` | string | | `error` | string | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/redirects?url=https%3A%2F%2Fexample.com&domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/redirects?url=https%3A%2F%2Fexample.com&domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/redirects?url=https%3A%2F%2Fexample.com&domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/redirects?url=https%3A%2F%2Fexample.com&domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/redirects?url=https%3A%2F%2Fexample.com&domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "original_url": "http://example.com", "final_url": "https://www.example.com/", "redirect_count": 2, "hops": [ { "url": "http://example.com", "status_code": 301, "location": "https://example.com/", "server": "nginx", "content_type": "text/html" }, { "url": "https://example.com/", "status_code": 301, "location": "https://www.example.com/", "server": "nginx", "content_type": "text/html" }, { "url": "https://www.example.com/", "status_code": 200, "server": "nginx", "content_type": "text/html; charset=UTF-8" } ], "https_upgrade": true, "domain_changed": true, "final_status": 200, "final_title": "Example Co | Home", "risk_summary": { "risk_level": "medium", "risk_flags": [ "domain_changed" ], "hop_count": 3, "redirect_count": 2, "https_upgrade": true, "https_downgrade": false, "domain_changed": true, "final_status": 200, "error_present": false, "tracking_parameter_hops": 0 }, "total_time_ms": 684, "checked_at": "2026-10-09T10:15:30.000Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/technology-detection # Tech Stack Detection API Detect the technology stack used by a website including CMS, frameworks, and services. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/tech-stack-api) ## Operations GET `/v1/tech` [View API reference](https://domscan.net/docs/products/technology-detection#getTechStack) POST `/v1/tech/bulk` [View API reference](https://domscan.net/docs/products/technology-detection#postTechStackBulk) POST `/v1/tech/jobs` [View API reference](https://domscan.net/docs/products/technology-detection#createTechScanJob) GET `/v1/tech/jobs` [View API reference](https://domscan.net/docs/products/technology-detection#listTechScanJobs) GET `/v1/tech/jobs/:job_id` [View API reference](https://domscan.net/docs/products/technology-detection#getTechScanJob) GET `/v1/tech/jobs/:job_id/results` [View API reference](https://domscan.net/docs/products/technology-detection#getTechScanJobResults) DELETE `/v1/tech/jobs/:job_id` [View API reference](https://domscan.net/docs/products/technology-detection#cancelTechScanJob) GET `/v1/hosting` [View API reference](https://domscan.net/docs/products/technology-detection#getHosting) POST `/v1/hosting/bulk` [View API reference](https://domscan.net/docs/products/technology-detection#bulkGetHosting) GET `/v1/parking` [View API reference](https://domscan.net/docs/products/technology-detection#getParkingDetection) GET `/v1/agent-readiness` [View API reference](https://domscan.net/docs/products/technology-detection#checkAgentReadiness)[Read the guide](https://domscan.net/agent-readiness-api) ## GET `/v1/tech` Operation: `getTechStack` Credits and authentication: 3-9 Authentication required GET /v1/tech Credits: 3-9 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | | mode | string Allowed values `fast`, `rendered`, `deep` Default `fast` | optional | | max_pages | integer Default `3` | optional | | skip_cache | string Allowed values `0`, `1` Default `0` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `url` | string | | `technologies[]` | object[] | | `technologies[]` | object | | `technologies[].id` | string | | `technologies[].name` | string | | `technologies[].category` | string | | `technologies[].version` | string | | `technologies[].version_kind` | string | | `technologies[].confidence` | string | | `technologies[].confidence_score` | integer | | `technologies[].evidence` | string | | `technologies[].evidence_details[]` | object[] | | `technologies[].evidence_details[]` | object | | `technologies[].evidence_details[].source` | string | | `technologies[].evidence_details[].key` | string | | `technologies[].evidence_details[].matched` | string | | `technologies[].evidence_details[].page_url` | string | | `technologies[].source_count` | integer | | `technologies[].caveats[]` | string[] | | `technologies[].reference` | object | | `technologies[].reference.website` | string | | `technologies[].reference.source_url` | string | | `technologies[].reference.source_owner` | string | | `technologies[].reference.source_kind` | string | | `technologies[].reference.access` | string | | `technologies[].reference.access_method` | string | | `technologies[].reference.cost` | string | | `technologies[].reference.terms_status` | string | | `technologies[].reference.expected_freshness` | string | | `technologies[].reference.maintenance_risk` | string | | `technologies[].reference.runtime_rate_limits` | string | | `technologies[].reference.fallback_behavior` | string | | `technologies[].reference.last_verified` | string | | `detection_summary` | object | | `detection_summary.detected_count` | integer | | `detection_summary.category_count` | integer | | `detection_summary.categories[]` | string[] | | `detection_summary.high_confidence_count` | integer | | `detection_summary.medium_confidence_count` | integer | | `detection_summary.low_confidence_count` | integer | | `detection_summary.versioned_count` | integer | | `detection_summary.evidence_sources` | object | | `detection_summary.evidence_sources.header` | integer | | `detection_summary.evidence_sources.html` | integer | | `detection_summary.evidence_sources.asset_url` | integer | | `detection_summary.evidence_sources.network_url` | integer | | `detection_summary.evidence_sources.javascript` | integer | | `detection_summary.evidence_sources.meta` | integer | | `detection_summary.evidence_sources.cookie` | integer | | `detection_summary.evidence_sources.url` | integer | | `detection_summary.catalog_size` | integer | | `detection_summary.catalog_category_count` | integer | | `detection_summary.summary_field_count` | integer | | `summary` | object | | `summary.cdn` | string | | `summary.server` | string | | `summary.framework` | string | | `summary.cms` | string | | `summary.hosting` | string | | `summary.platform` | string | | `summary.analytics[]` | string[] | | `headers` | object | | `meta` | object | | `ssl` | object | | `ssl.enabled` | boolean | | `analysis` | object | | `analysis.status` | string | | `analysis.requested_url` | string | | `analysis.final_url` | string | | `analysis.response_status` | integer | | `analysis.redirect_count` | integer | | `analysis.relay_used` | boolean | | `analysis.signals_checked[]` | string[] | | `analysis.signals_unavailable[]` | string[] | | `analysis.html_characters_analyzed` | integer | | `analysis.html_bytes_analyzed` | integer | | `analysis.html_byte_limit` | integer | | `analysis.html_truncated` | boolean | | `analysis.response_body_truncated` | boolean | | `analysis.mode` | string | | `analysis.rendered` | boolean | | `analysis.javascript_executed` | boolean | | `analysis.pages_requested` | integer | | `analysis.pages_analyzed` | integer | | `analysis.page_limit` | integer | | `analysis.network_requests_observed` | integer | | `analysis.page_limit_reached` | boolean | | `analysis.resource_limit_reached` | boolean | | `analysis.redirected_to_different_host` | boolean | | `analysis.no_detection_reason` | string \| null | | `analysis.recommended_mode` | string \| null | | `analysis.pages[]` | object[] | | `analysis.pages[]` | object | | `analysis.pages[].url` | string | | `analysis.pages[].status` | integer | | `analysis.pages[].html_truncated` | boolean | | `analysis.pages[].network_requests_observed` | integer | | `total_time_ms` | integer | | `checked_at` | string | | `_meta` | object | | `_meta.served_by` | string | | `_meta.analysis_status` | string | | `_meta.response_status` | integer | | `_meta.cache_status` | string | | `_meta.stale` | boolean | | `_meta.cached_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tech?url=https%3A%2F%2Fexample.com&domain=example.com&mode=fast&max_pages=3&skip_cache=0" ``` ```javascript const response = await fetch("https://domscan.net/v1/tech?url=https%3A%2F%2Fexample.com&domain=example.com&mode=fast&max_pages=3&skip_cache=0", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tech?url=https%3A%2F%2Fexample.com&domain=example.com&mode=fast&max_pages=3&skip_cache=0", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tech?url=https%3A%2F%2Fexample.com&domain=example.com&mode=fast&max_pages=3&skip_cache=0", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech?url=https%3A%2F%2Fexample.com&domain=example.com&mode=fast&max_pages=3&skip_cache=0") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "url": "https://example.com", "technologies": [ { "id": "example-id", "name": "example", "category": "example", "confidence": "high", "confidence_score": 85, "evidence": "example", "evidence_details": [ { "source": "header", "matched": "example", "key": "example", "page_url": "https://example.com" } ], "source_count": 1, "caveats": [ "example" ], "reference": { "website": "https://example.com", "source_url": "https://example.com", "source_owner": "example", "source_kind": "official_docs", "access": "public", "access_method": "target_response_inspection", "cost": "none", "terms_status": "public_source_reviewed_factual_signature", "expected_freshness": "reverify_on_source_or_signature_change", "maintenance_risk": "low", "runtime_rate_limits": "not_applicable_no_source_request", "fallback_behavior": "unmatched_or_unavailable_signal_is_not_detected", "last_verified": "2026-08-27" }, "version": "2.15.0", "version_kind": "product" } ], "detection_summary": { "detected_count": 1, "category_count": 1, "categories": [ "example" ], "high_confidence_count": 1, "medium_confidence_count": 1, "low_confidence_count": 1, "versioned_count": 1, "evidence_sources": { "header": 1, "html": 1, "asset_url": 1, "network_url": 1, "javascript": 1, "meta": 1, "cookie": 1, "url": 1 }, "catalog_size": 1, "catalog_category_count": 1, "summary_field_count": 1 }, "summary": { "cdn": "example", "server": "example", "framework": "example", "cms": "example", "hosting": "example", "platform": "example", "analytics": [ "example" ] }, "headers": {}, "meta": {}, "ssl": { "enabled": false }, "analysis": { "status": "complete", "requested_url": "https://example.com", "final_url": "https://example.com", "response_status": 1, "redirect_count": 1, "relay_used": false, "signals_checked": [ "header" ], "signals_unavailable": [ "header" ], "html_characters_analyzed": 1, "html_bytes_analyzed": 1, "html_byte_limit": 1, "html_truncated": false, "response_body_truncated": false, "mode": "fast", "rendered": false, "javascript_executed": false, "pages_requested": 1, "pages_analyzed": 1, "page_limit": 1, "network_requests_observed": 1, "page_limit_reached": false, "resource_limit_reached": false, "redirected_to_different_host": false, "no_detection_reason": "redirected_to_different_host", "recommended_mode": "rendered", "pages": [ { "url": "https://example.com", "status": 1, "html_truncated": false, "network_requests_observed": 1 } ] }, "total_time_ms": 1, "checked_at": "2026-08-27T12:00:00Z", "_meta": { "served_by": "example", "analysis_status": "ok", "response_status": 1, "cache_status": "miss", "stale": false, "cached_at": "2026-08-27T12:00:00Z" }, "cache_age_s": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable ## POST `/v1/tech/bulk` Operation: `postTechStackBulk` Credits and authentication: 3 Authentication required POST /v1/tech/bulk Credits: 3/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | mode | string Allowed values `fast` Default `fast` | optional | | targets | unknown[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `results[].index` | integer | | `results[].input` | string | | `results[].reference` | string | | `results[].status` | string | | `results[].data` | object | | `results[].error` | object | | `results[].error.code` | string | | `results[].error.message` | string | | `results[].error.status` | integer | | `results[].error.retryable` | boolean | | `results[].billing` | object | | `results[].billing.credits_charged` | integer | | `results[].billing.credits_refunded` | integer | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.mode` | string | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.credits_charged` | integer | | `meta.credits_refunded` | integer | | `meta.analysis_status` | string | | `meta.detected_count` | integer | | `meta.empty_result` | boolean | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/tech/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "mode": "fast", "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "crm-42" } ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tech/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "mode": "fast", "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "crm-42" } ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tech/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "mode": "fast", "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "crm-42", }, ], }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "mode": "fast", "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "crm-42" } ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tech/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "mode" => "fast", "targets" => [ "example.com", { "url" => "https://shop.example.com/", "reference" => "crm-42" } ] }) #### Example response ```json { "results": [ { "index": 1, "input": "example", "status": "succeeded", "billing": { "credits_charged": 1, "credits_refunded": 1 }, "reference": "example", "data": {}, "error": { "code": "example", "message": "Request completed", "status": 1, "retryable": false } } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "mode": "fast", "max_items": 10, "credits_per_item": 3, "credits_charged": 1, "credits_refunded": 1, "analysis_status": "complete", "detected_count": 1, "empty_result": false, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests - `503` Service Unavailable ## POST `/v1/tech/jobs` Operation: `createTechScanJob` Credits and authentication: 3 Authentication required POST /v1/tech/jobs Credits: 3/item #### Body parameters | Parameter | Type | required | | --- | --- | --- | | notify_webhook | unknown | optional | | mode | string Allowed values `fast`, `rendered`, `deep` Default `fast` | optional | | max_pages | integer | optional | | targets | unknown[] | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.max_pages` | integer | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_per_item` | integer | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | | `idempotent_replay` | boolean | #### Example request ```bash curl -X POST "https://domscan.net/v1/tech/jobs" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "mode": "deep", "max_pages": 3, "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "shop" } ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tech/jobs", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "mode": "deep", "max_pages": 3, "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "shop" } ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tech/jobs", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "mode": "deep", "max_pages": 3, "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "shop", }, ], }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "mode": "deep", "max_pages": 3, "targets": [ "example.com", { "url": "https://shop.example.com/", "reference": "shop" } ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tech/jobs", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech/jobs") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "mode" => "deep", "max_pages" => 3, "targets" => [ "example.com", { "url" => "https://shop.example.com/", "reference" => "shop" } ] }) #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "fast", "max_pages": 1, "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_per_item": 3, "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" }, "idempotent_replay": false } ``` #### HTTP status codes - `202` Accepted - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `429` Too Many Requests - `503` Service Unavailable ## GET `/v1/tech/jobs` Operation: `listTechScanJobs` Credits and authentication: Free Authentication required GET /v1/tech/jobs Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer Default `25` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `jobs[]` | object[] | | `jobs[]` | object | | `jobs[].id` | string | | `jobs[].status` | string | | `jobs[].mode` | string | | `jobs[].max_pages` | integer | | `jobs[].total` | integer | | `jobs[].counts` | object | | `jobs[].counts.pending` | integer | | `jobs[].counts.processing` | integer | | `jobs[].counts.succeeded` | integer | | `jobs[].counts.failed` | integer | | `jobs[].counts.cancelled` | integer | | `jobs[].billing` | object | | `jobs[].billing.credits_per_item` | integer | | `jobs[].billing.credits_charged` | integer | | `jobs[].billing.credits_refunded` | integer | | `jobs[].billing.credits_net` | integer | | `jobs[].status_url` | string | | `jobs[].results_url` | string | | `jobs[].poll_after_ms` | integer \| null | | `jobs[].created_at` | string | | `jobs[].started_at` | string \| null | | `jobs[].completed_at` | string \| null | | `jobs[].cancelled_at` | string \| null | | `jobs[].updated_at` | string | | `jobs[].processing_deadline_at` | string | | `jobs[].results_expires_at` | string | | `pagination` | object | | `pagination.limit` | integer | | `pagination.next_cursor` | string \| null | | `pagination.has_more` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tech/jobs?limit=25&cursor=example" ``` ```javascript const response = await fetch("https://domscan.net/v1/tech/jobs?limit=25&cursor=example", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tech/jobs?limit=25&cursor=example", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tech/jobs?limit=25&cursor=example", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech/jobs?limit=25&cursor=example") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "jobs": [ { "id": "example-id", "status": "queued", "mode": "fast", "max_pages": 1, "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_per_item": 3, "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } ], "pagination": { "limit": 1, "next_cursor": "example", "has_more": false } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `429` Too Many Requests ## GET `/v1/tech/jobs/:job_id` Operation: `getTechScanJob` Credits and authentication: Free Authentication required GET /v1/tech/jobs/:job_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.max_pages` | integer | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_per_item` | integer | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tech/jobs/string" ``` ```javascript const response = await fetch("https://domscan.net/v1/tech/jobs/string", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tech/jobs/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tech/jobs/string", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech/jobs/string") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "fast", "max_pages": 1, "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_per_item": 3, "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/tech/jobs/:job_id/results` Operation: `getTechScanJobResults` Credits and authentication: Free Authentication required GET /v1/tech/jobs/:job_id/results Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | | cursor | string | optional | | limit | integer Default `25` | optional | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.max_pages` | integer | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_per_item` | integer | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | | `results[]` | object[] | | `results[]` | object | | `results[].index` | integer | | `results[].input` | string | | `results[].reference` | string | | `results[].status` | string | | `results[].data` | object | | `results[].error` | object | | `results[].billing` | object | | `results[].analysis_status` | string \| null | | `results[].detected_count` | integer \| null | | `pagination` | object | | `pagination.limit` | integer | | `pagination.next_cursor` | string \| null | | `pagination.has_more` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tech/jobs/example/results?cursor=example&limit=25" ``` ```javascript const response = await fetch("https://domscan.net/v1/tech/jobs/example/results?cursor=example&limit=25", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tech/jobs/example/results?cursor=example&limit=25", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tech/jobs/example/results?cursor=example&limit=25", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech/jobs/example/results?cursor=example&limit=25") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "fast", "max_pages": 1, "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_per_item": 3, "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" }, "results": [ { "index": 1, "input": "example", "status": "pending", "billing": {}, "reference": "example", "data": {}, "error": {}, "analysis_status": "available", "detected_count": 1 } ], "pagination": { "limit": 1, "next_cursor": "example", "has_more": false } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `410` HTTP 410 - `429` Too Many Requests ## DELETE `/v1/tech/jobs/:job_id` Operation: `cancelTechScanJob` Credits and authentication: Free Authentication required DELETE /v1/tech/jobs/:job_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.mode` | string | | `job.max_pages` | integer | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_per_item` | integer | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | #### Example request ```bash curl -X DELETE "https://domscan.net/v1/tech/jobs/string" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/tech/jobs/string", { method: "DELETE", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.delete( "https://domscan.net/v1/tech/jobs/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodDelete, "https://domscan.net/v1/tech/jobs/string", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tech/jobs/string") request = Net::HTTP::Delete.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "job": { "id": "example-id", "status": "queued", "mode": "fast", "max_pages": 1, "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_per_item": 3, "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `202` Accepted - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/hosting` Operation: `getHosting` Credits and authentication: 3 Authentication required GET /v1/hosting Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `hosting` | object | | `hosting.provider` | string | | `hosting.provider_id` | string | | `hosting.confidence` | number | | `hosting.region` | string | | `hosting.detection_method` | string | | `cdn` | object | | `cdn.detected` | boolean | | `cdn.provider` | string | | `cdn.provider_id` | string | | `cdn.confidence` | number | | `cdn.detection_method` | string | | `cdn.features[]` | string[] | | `waf` | object | | `waf.detected` | boolean | | `waf.provider` | string | | `waf.provider_id` | string | | `waf.confidence` | number | | `waf.detection_method` | string | | `dns_provider` | object | | `dns_provider.provider` | string | | `dns_provider.provider_id` | string | | `dns_provider.nameservers[]` | string[] | | `dns_provider.confidence` | number | | `dns_providers[]` | object[] | | `dns_providers[]` | object | | `dns_providers[].provider_id` | string | | `dns_providers[].provider` | string | | `email_provider` | object | | `email_provider.provider` | string | | `email_provider.provider_id` | string | | `email_provider.mx_records[]` | string[] | | `email_provider.confidence` | number | | `ssh` | object | | `ssh.host` | string | | `ssh.port` | integer | | `ssh.reachable` | boolean | | `ssh.banner` | string \| null | | `ssh.algorithms[]` | string[] | | `ssh.weak_algorithms[]` | string[] | | `ssh.keys[]` | object[] | | `ssh.keys[]` | object | | `ssh.keys[].host` | string | | `ssh.keys[].algorithm` | string | | `ssh.keys[].key_size` | integer \| null | | `ssh.keys[].fingerprint_sha256` | string \| null | | `ssh.keys[].weak` | boolean | | `ssh.keys[].weak_reasons[]` | string[] | | `ssh.error` | string \| null | | `ssh.checked_at` | string | | `provider_summary` | object | | `provider_summary.cache_status` | string | | `provider_summary.provider_count` | integer | | `provider_summary.detected_surfaces[]` | string[] | | `provider_summary.confidence` | string | | `provider_summary.confidence_score` | integer | | `provider_summary.hosting_provider` | string \| null | | `provider_summary.cdn_provider` | string \| null | | `provider_summary.waf_provider` | string \| null | | `provider_summary.dns_provider_count` | integer | | `provider_summary.email_provider` | string \| null | | `provider_summary.ssh_exposed` | boolean \| null | | `provider_summary.evidence[]` | object[] | | `provider_summary.evidence[]` | object | | `provider_summary.evidence[].surface` | string | | `provider_summary.evidence[].provider` | string | | `provider_summary.evidence[].confidence` | number \| null | | `provider_summary.evidence[].method` | string \| null | | `ip_info` | object | | `ip_info.ipv4[]` | string[] | | `ip_info.ipv6[]` | string[] | | `checked_at` | string | | `check_duration_ms` | integer | | `meta` | object | | `meta.cached` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/hosting?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/hosting?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/hosting?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/hosting?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/hosting?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "github.com", "hosting": { "provider": "Microsoft Azure", "provider_id": "azure", "confidence": 0.86, "detection_method": "ip_range" }, "cdn": { "detected": true, "provider": "Fastly", "provider_id": "fastly", "confidence": 0.94, "detection_method": "headers" }, "waf": { "detected": false, "confidence": 0.2, "detection_method": "headers" }, "dns_provider": { "provider": "AWS Route 53", "provider_id": "route53", "nameservers": [ "ns-1283.awsdns-32.org", "ns-1707.awsdns-21.co.uk" ], "confidence": 0.9 }, "email_provider": { "provider": "Google Workspace", "provider_id": "google_workspace", "mx_records": [ "aspmx.l.google.com" ], "confidence": 0.95 }, "ssh": { "host": "github.com", "port": 22, "reachable": true, "banner": "SSH-2.0-babeld", "algorithms": [ "ssh-ed25519", "ecdsa-sha2-nistp256" ], "weak_algorithms": [], "keys": [ { "host": "github.com", "algorithm": "ssh-ed25519", "key_size": 256, "fingerprint_sha256": "SHA256:+DiY3wvvV6TuJJhbpZisF/Ym7N3QKXNoZk6sJ2x2d2s", "weak": false, "weak_reasons": [] } ], "error": null, "checked_at": "2026-04-18T21:00:00Z" }, "provider_summary": { "cache_status": "miss", "provider_count": 4, "detected_surfaces": [ "hosting", "cdn", "dns", "email", "ssh" ], "confidence": "high", "confidence_score": 92, "hosting_provider": "Microsoft Azure", "cdn_provider": "Fastly", "waf_provider": null, "dns_provider_count": 1, "email_provider": "Google Workspace", "ssh_exposed": true, "evidence": [ { "surface": "hosting", "provider": "Microsoft Azure", "confidence": 0.86, "method": "ip_range" }, { "surface": "cdn", "provider": "Fastly", "confidence": 0.94, "method": "headers" }, { "surface": "dns", "provider": "AWS Route 53", "confidence": 0.9, "method": "ns" }, { "surface": "email", "provider": "Google Workspace", "confidence": 0.95, "method": "mx" }, { "surface": "ssh", "provider": "public-ssh", "confidence": 90, "method": "edge-relay" } ] }, "ip_info": { "ipv4": [ "140.82.121.4" ], "ipv6": [] }, "checked_at": "2026-04-18T21:00:00Z", "check_duration_ms": 156 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/hosting/bulk` Operation: `bulkGetHosting` Credits and authentication: 3 Authentication required POST /v1/hosting/bulk Credits: 3/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/hosting/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "cloudflare.com" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/hosting/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "cloudflare.com" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/hosting/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "cloudflare.com", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "cloudflare.com" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/hosting/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/hosting/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "cloudflare.com" ] }) #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/parking` Operation: `getParkingDetection` Credits and authentication: 2 Authentication required GET /v1/parking Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `is_parked` | boolean \| null | | `is_for_sale` | boolean \| null | | `parking_provider` | string \| null | | `aftermarket_listings[]` | object[] | | `aftermarket_listings[]` | object | | `aftermarket_listings[].platform` | string | | `aftermarket_listings[].detected_via` | string | | `signals[]` | object[] | | `signals[]` | object | | `signals[].type` | string | | `signals[].detail` | string | | `signals[].provider` | string | | `confidence` | number | | `checked_at` | string | | `check_duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/parking?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/parking?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/parking?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/parking?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/parking?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "parked-example.com", "is_parked": true, "is_for_sale": false, "parking_provider": "Sedo", "aftermarket_listings": [ { "platform": "Sedo", "detected_via": "dns" } ], "signals": [ { "type": "nameserver", "detail": "NS record: ns1.sedoparking.com", "provider": "Sedo" }, { "type": "nameserver", "detail": "NS record: ns2.sedoparking.com", "provider": "Sedo" } ], "confidence": 0.85, "checked_at": "2026-10-09T10:15:30.000Z", "check_duration_ms": 842 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/agent-readiness` Operation: `checkAgentReadiness` Credits and authentication: 3 Authentication required GET /v1/agent-readiness Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | | skip_cache | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `requested_url` | string | | `final_url` | string | | `checked_at` | string | | `outcome` | string | | `fetch_state` | string | | `http_status` | integer \| null | | `summary` | object | | `summary.coverage` | string | | `summary.detected_signals` | integer | | `summary.total_signals` | integer | | `summary.score` | integer \| null | | `summary.rating` | string | | `summary.confidence` | integer | | `summary.passed_checks` | integer | | `summary.warning_checks` | integer | | `summary.failed_checks` | integer | | `summary.unknown_checks` | integer | | `summary.not_applicable_checks` | integer | | `signals` | object | | `signals.webmcp` | object | | `signals.webmcp.status` | string | | `signals.webmcp.validation` | string | | `signals.webmcp.method` | string | | `signals.webmcp.checked_url` | string \| null | | `signals.webmcp.http_status` | integer \| null | | `signals.webmcp.evidence[]` | string[] | | `signals.webmcp.caveats[]` | string[] | | `signals.remote_mcp` | object | | `signals.remote_mcp.status` | string | | `signals.remote_mcp.validation` | string | | `signals.remote_mcp.method` | string | | `signals.remote_mcp.checked_url` | string \| null | | `signals.remote_mcp.http_status` | integer \| null | | `signals.remote_mcp.evidence[]` | string[] | | `signals.remote_mcp.caveats[]` | string[] | | `signals.openapi` | object | | `signals.openapi.status` | string | | `signals.openapi.validation` | string | | `signals.openapi.method` | string | | `signals.openapi.checked_url` | string \| null | | `signals.openapi.http_status` | integer \| null | | `signals.openapi.evidence[]` | string[] | | `signals.openapi.caveats[]` | string[] | | `signals.llms_txt` | object | | `signals.llms_txt.status` | string | | `signals.llms_txt.validation` | string | | `signals.llms_txt.method` | string | | `signals.llms_txt.checked_url` | string \| null | | `signals.llms_txt.http_status` | integer \| null | | `signals.llms_txt.evidence[]` | string[] | | `signals.llms_txt.caveats[]` | string[] | | `signals.api_catalog` | object | | `signals.api_catalog.status` | string | | `signals.api_catalog.validation` | string | | `signals.api_catalog.method` | string | | `signals.api_catalog.checked_url` | string \| null | | `signals.api_catalog.http_status` | integer \| null | | `signals.api_catalog.evidence[]` | string[] | | `signals.api_catalog.caveats[]` | string[] | | `signals.mcp_server_card` | object | | `signals.mcp_server_card.status` | string | | `signals.mcp_server_card.validation` | string | | `signals.mcp_server_card.method` | string | | `signals.mcp_server_card.checked_url` | string \| null | | `signals.mcp_server_card.http_status` | integer \| null | | `signals.mcp_server_card.evidence[]` | string[] | | `signals.mcp_server_card.caveats[]` | string[] | | `signals.agent_skills` | object | | `signals.agent_skills.status` | string | | `signals.agent_skills.validation` | string | | `signals.agent_skills.method` | string | | `signals.agent_skills.checked_url` | string \| null | | `signals.agent_skills.http_status` | integer \| null | | `signals.agent_skills.evidence[]` | string[] | | `signals.agent_skills.caveats[]` | string[] | | `signals.oauth` | object | | `signals.oauth.status` | string | | `signals.oauth.validation` | string | | `signals.oauth.method` | string | | `signals.oauth.checked_url` | string \| null | | `signals.oauth.http_status` | integer \| null | | `signals.oauth.evidence[]` | string[] | | `signals.oauth.caveats[]` | string[] | | `signals.markdown` | object | | `signals.markdown.status` | string | | `signals.markdown.validation` | string | | `signals.markdown.method` | string | | `signals.markdown.checked_url` | string \| null | | `signals.markdown.http_status` | integer \| null | | `signals.markdown.evidence[]` | string[] | | `signals.markdown.caveats[]` | string[] | | `signals.web_bot_auth` | object | | `signals.web_bot_auth.status` | string | | `signals.web_bot_auth.validation` | string | | `signals.web_bot_auth.method` | string | | `signals.web_bot_auth.checked_url` | string \| null | | `signals.web_bot_auth.http_status` | integer \| null | | `signals.web_bot_auth.evidence[]` | string[] | | `signals.web_bot_auth.caveats[]` | string[] | | `signals.sitemap_markdown` | object | | `signals.sitemap_markdown.status` | string | | `signals.sitemap_markdown.validation` | string | | `signals.sitemap_markdown.method` | string | | `signals.sitemap_markdown.checked_url` | string \| null | | `signals.sitemap_markdown.http_status` | integer \| null | | `signals.sitemap_markdown.evidence[]` | string[] | | `signals.sitemap_markdown.caveats[]` | string[] | | `signals.agent_guide` | object | | `signals.agent_guide.status` | string | | `signals.agent_guide.validation` | string | | `signals.agent_guide.method` | string | | `signals.agent_guide.checked_url` | string \| null | | `signals.agent_guide.http_status` | integer \| null | | `signals.agent_guide.evidence[]` | string[] | | `signals.agent_guide.caveats[]` | string[] | | `foundations` | object | | `dimensions` | object | | `dimensions.discoverability` | object | | `dimensions.discoverability.score` | integer \| null | | `dimensions.discoverability.confidence` | integer | | `dimensions.discoverability.passed` | integer | | `dimensions.discoverability.warned` | integer | | `dimensions.discoverability.failed` | integer | | `dimensions.discoverability.unknown` | integer | | `dimensions.discoverability.not_applicable` | integer | | `dimensions.discoverability.checks[]` | string[] | | `dimensions.content` | object | | `dimensions.content.score` | integer \| null | | `dimensions.content.confidence` | integer | | `dimensions.content.passed` | integer | | `dimensions.content.warned` | integer | | `dimensions.content.failed` | integer | | `dimensions.content.unknown` | integer | | `dimensions.content.not_applicable` | integer | | `dimensions.content.checks[]` | string[] | | `dimensions.access_policy` | object | | `dimensions.access_policy.score` | integer \| null | | `dimensions.access_policy.confidence` | integer | | `dimensions.access_policy.passed` | integer | | `dimensions.access_policy.warned` | integer | | `dimensions.access_policy.failed` | integer | | `dimensions.access_policy.unknown` | integer | | `dimensions.access_policy.not_applicable` | integer | | `dimensions.access_policy.checks[]` | string[] | | `dimensions.capabilities` | object | | `dimensions.capabilities.score` | integer \| null | | `dimensions.capabilities.confidence` | integer | | `dimensions.capabilities.passed` | integer | | `dimensions.capabilities.warned` | integer | | `dimensions.capabilities.failed` | integer | | `dimensions.capabilities.unknown` | integer | | `dimensions.capabilities.not_applicable` | integer | | `dimensions.capabilities.checks[]` | string[] | | `checks` | object | | `recommendations[]` | object[] | | `recommendations[]` | object | | `recommendations[].code` | string | | `recommendations[].severity` | string | | `meta` | object | | `meta.cached` | boolean | | `meta.fetch_path` | string | | `meta.duration_ms` | integer | | `meta.probe_count` | integer | | `meta.body_truncated` | boolean | | `meta.source_version` | string | | `meta.last_verified` | string | | `meta.rubric_version` | string | | `meta.max_probes` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/agent-readiness?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/agent-readiness?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/agent-readiness?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/agent-readiness?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/agent-readiness?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "requested_url": "https://www.example.com/", "final_url": "https://www.example.com/", "checked_at": "2026-10-09T10:15:30.000Z", "outcome": "partial", "fetch_state": "ok", "http_status": 200, "summary": { "coverage": "multi_channel", "detected_signals": 3, "total_signals": 12, "score": 78, "rating": "good", "confidence": 95, "passed_checks": 18, "warning_checks": 12, "failed_checks": 2, "unknown_checks": 2, "not_applicable_checks": 8 }, "signals": { "webmcp": { "status": "unknown", "validation": "runtime_required", "method": "static_html", "checked_url": "https://www.example.com/", "http_status": 200, "evidence": [], "caveats": [ "runtime_observation_required" ] }, "remote_mcp": { "status": "not_detected", "validation": "not_applicable", "method": "oauth_protected_resource_metadata", "checked_url": "https://www.example.com/.well-known/oauth-protected-resource/mcp", "http_status": 404, "evidence": [ "exact_missing_response" ], "caveats": [ "custom_or_unauthenticated_endpoints_not_checked" ] }, "openapi": { "status": "detected", "validation": "confirmed", "method": "service_description", "checked_url": "https://www.example.com/openapi.json", "http_status": 200, "evidence": [ "openapi_document_validated" ], "caveats": [] }, "llms_txt": { "status": "detected", "validation": "confirmed", "method": "well_known_path", "checked_url": "https://www.example.com/llms.txt", "http_status": 200, "evidence": [ "markdown_h1", "markdown_links_1" ], "caveats": [] }, "api_catalog": { "status": "detected", "validation": "confirmed", "method": "rfc9727_api_catalog", "checked_url": "https://www.example.com/.well-known/api-catalog", "http_status": 200, "evidence": [ "service_descriptions_1", "api_catalog_link_header" ], "caveats": [] }, "mcp_server_card": { "status": "not_detected", "validation": "not_applicable", "method": "mcp_server_card", "checked_url": null, "http_status": null, "evidence": [ "bounded_candidates_missing" ], "caveats": [] }, "agent_skills": { "status": "not_detected", "validation": "not_applicable", "method": "agent_skills_index", "checked_url": "https://www.example.com/.well-known/agent-skills/index.json", "http_status": 404, "evidence": [ "exact_missing_response" ], "caveats": [] }, "oauth": { "status": "not_detected", "validation": "not_applicable", "method": "oauth_server_metadata", "checked_url": null, "http_status": null, "evidence": [ "bounded_candidates_missing" ], "caveats": [] }, "markdown": { "status": "not_detected", "validation": "not_applicable", "method": "accept_content_negotiation", "checked_url": "https://www.example.com/", "http_status": 200, "evidence": [ "html_returned_for_markdown_accept" ], "caveats": [] }, "web_bot_auth": { "status": "not_detected", "validation": "not_applicable", "method": "web_bot_auth_directory", "checked_url": "https://www.example.com/.well-known/http-message-signatures-directory", "http_status": 404, "evidence": [ "exact_missing_response" ], "caveats": [] }, "sitemap_markdown": { "status": "not_detected", "validation": "not_applicable", "method": "markdown_sitemap", "checked_url": null, "http_status": null, "evidence": [ "bounded_candidates_missing" ], "caveats": [] }, "agent_guide": { "status": "not_detected", "validation": "not_applicable", "method": "public_agent_guide", "checked_url": null, "http_status": null, "evidence": [ "bounded_candidates_missing" ], "caveats": [] } }, "foundations": { "https": { "state": "pass", "evidence": [ "https" ] }, "indexable": { "state": "pass", "evidence": [ "no_noindex_directive" ] }, "robots": { "state": "pass", "evidence": [ "robots_allows_crawl" ] }, "title": { "state": "pass", "evidence": [ "title_present" ] }, "meta_description": { "state": "pass", "evidence": [ "meta_description_present" ] }, "canonical": { "state": "warn", "evidence": [ "canonical_missing" ] }, "language": { "state": "pass", "evidence": [ "html_lang_present" ] }, "structured_data": { "state": "warn", "evidence": [ "json_ld_not_detected" ] }, "labeled_forms": { "state": "pass", "evidence": [ "no_form_controls" ] }, "origin_isolation": { "state": "unknown", "evidence": [ "origin_agent_cluster_not_declared" ] }, "webmcp_permission": { "state": "pass", "evidence": [ "tools_permission_default_self" ] } }, "dimensions": { "discoverability": { "score": 84, "confidence": 100, "passed": 8, "warned": 1, "failed": 2, "unknown": 0, "not_applicable": 1, "checks": [ "https", "http_response", "redirect_chain", "html_content_type", "indexable", "robots_access", "sitemap_xml", "sitemap_lastmod", "target_discoverable", "llms_txt", "sitemap_markdown", "api_catalog_link" ] }, "content": { "score": 67, "confidence": 100, "passed": 5, "warned": 8, "failed": 0, "unknown": 0, "not_applicable": 2, "checks": [ "title", "meta_description", "open_graph", "canonical", "language", "structured_data", "heading_structure", "content_density", "form_controls", "markdown_negotiation", "markdown_alternate", "code_languages", "api_schema_link", "glossary_context", "public_agent_guide" ] }, "access_policy": { "score": 88, "confidence": 100, "passed": 2, "warned": 1, "failed": 0, "unknown": 0, "not_applicable": 2, "checks": [ "ai_bot_access", "explicit_ai_policy", "content_signals", "agent_content_directives", "web_bot_auth" ] }, "capabilities": { "score": 83, "confidence": 75, "passed": 3, "warned": 2, "failed": 0, "unknown": 2, "not_applicable": 3, "checks": [ "webmcp", "remote_mcp", "openapi", "api_catalog", "mcp_server_card", "agent_skills", "oauth_discovery", "service_description_link", "origin_isolation", "webmcp_permission" ] } }, "checks": { "https": { "id": "https", "dimension": "discoverability", "state": "pass", "weight": 3, "method": "document_analysis", "checked_url": "https://www.example.com/", "http_status": 200, "evidence": [ "https" ], "caveats": [], "reference": "HTTPS", "maturity": "standard" }, "http_response": { "id": "http_response", "dimension": "discoverability", "state": "pass", "weight": 3, "method": "document_analysis", "checked_url": "https://www.example.com/", "http_status": 200, "evidence": [ "http_status_200" ], "caveats": [], "reference": "HTTP semantics", "maturity": "standard" }, "llms_txt": { "id": "llms_txt", "dimension": "discoverability", "state": "pass", "weight": 2, "method": "well_known_path", "checked_url": "https://www.example.com/llms.txt", "http_status": 200, "evidence": [ "markdown_h1", "markdown_links_1" ], "caveats": [], "reference": "llms.txt proposal", "maturity": "proposal" } }, "recommendations": [ { "code": "ADD_CANONICAL", "severity": "medium" }, { "code": "ADD_STRUCTURED_DATA", "severity": "low" }, { "code": "PUBLISH_MCP_METADATA", "severity": "medium" } ], "meta": { "cached": false, "fetch_path": "primary", "duration_ms": 1840, "probe_count": 22, "body_truncated": false, "source_version": "2026-08-28", "last_verified": "2026-08-28", "rubric_version": "2026-08-28.3", "max_probes": 32 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/robots-txt # Robots.txt API API Parse robots.txt, test any crawler and path, and see which AI crawlers are blocked. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/robots-txt-api) ## Operations GET `/v1/robots` [View API reference](https://domscan.net/docs/products/robots-txt#getRobotsTxt) ## GET `/v1/robots` Operation: `getRobotsTxt` Credits and authentication: 1 Authentication required GET /v1/robots Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | | user_agent | string Default `*` | optional | | path | string | optional | | skip_cache | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `domain` | string | | `url` | string | | `robots_url` | string | | `status` | string | | `checked_at` | string | | `fetch` | object | | `fetch.checked_url` | string | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string \| null | | `fetch.via_proxy` | boolean \| null | | `fetch.redirect_count` | integer \| null | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer \| null | | `fetch.truncated` | boolean | | `fetch.error` | string \| null | | `sitemaps[]` | string[] | | `groups[]` | object[] | | `groups[]` | object | | `groups[].user_agents[]` | string[] | | `groups[].rules[]` | object[] | | `groups[].rules[]` | object | | `groups[].rules[].type` | string | | `groups[].rules[].path` | string | | `groups[].rules[].line` | integer | | `groups[].crawl_delay` | number \| null | | `other_directives[]` | object[] | | `other_directives[]` | object | | `other_directives[].name` | string | | `other_directives[].count` | integer | | `other_directives[].standard` | boolean | | `test` | object | | `test.user_agent` | string | | `test.path` | string | | `test.allowed` | boolean \| null | | `test.matched_rule` | object | | `test.matched_rule.type` | string | | `test.matched_rule.path` | string | | `test.matched_rule.line` | integer | | `test.matched_group` | string \| null | | `test.matched_user_agents[]` | string[] | | `test.reason` | string | | `ai_crawlers[]` | object[] | | `ai_crawlers[]` | object | | `ai_crawlers[].user_agent` | string | | `ai_crawlers[].owner` | string | | `ai_crawlers[].purpose` | string | | `ai_crawlers[].root_access` | string | | `ai_crawlers[].group` | string \| null | | `issues[]` | object[] | | `issues[]` | object | | `issues[].code` | string | | `issues[].count` | integer | | `issues[].lines[]` | integer[] | | `caveats[]` | string[] | | `summary` | object | | `summary.groups` | integer | | `summary.rules` | integer | | `summary.allow_rules` | integer | | `summary.disallow_rules` | integer | | `summary.sitemaps` | integer | | `summary.issues` | integer | | `summary.lines` | integer | | `summary.ai_crawlers_allowed` | integer | | `summary.ai_crawlers_disallowed` | integer | | `summary.ai_crawlers_partial` | integer | | `summary.ai_crawlers_unknown` | integer | | `summary.ai_crawlers_with_specific_group` | integer | | `meta` | object | | `meta.cached` | boolean | | `meta.duration_ms` | integer | | `meta.source_version` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/robots?url=https%3A%2F%2Fexample.com&domain=example.com&user_agent=GPTBot&path=%2Fadmin%2Fsettings&skip_cache=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/robots?url=https%3A%2F%2Fexample.com&domain=example.com&user_agent=GPTBot&path=%2Fadmin%2Fsettings&skip_cache=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/robots?url=https%3A%2F%2Fexample.com&domain=example.com&user_agent=GPTBot&path=%2Fadmin%2Fsettings&skip_cache=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/robots?url=https%3A%2F%2Fexample.com&domain=example.com&user_agent=GPTBot&path=%2Fadmin%2Fsettings&skip_cache=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/robots?url=https%3A%2F%2Fexample.com&domain=example.com&user_agent=GPTBot&path=%2Fadmin%2Fsettings&skip_cache=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "url": "https://example.com/", "robots_url": "https://example.com/robots.txt", "status": "found", "checked_at": "2026-10-09T10:15:30.000Z", "fetch": { "checked_url": "https://example.com/robots.txt", "http_status": 200, "final_url": "https://example.com/robots.txt", "via_proxy": true, "redirect_count": 0, "content_type": "text/plain; charset=utf-8", "bytes": 180, "truncated": false, "error": null }, "sitemaps": [ "https://example.com/sitemap.xml" ], "groups": [ { "user_agents": [ "GPTBot", "CCBot" ], "rules": [ { "type": "disallow", "path": "/", "line": 3 } ], "crawl_delay": null }, { "user_agents": [ "*" ], "rules": [ { "type": "disallow", "path": "/admin/", "line": 6 }, { "type": "allow", "path": "/admin/public$", "line": 7 } ], "crawl_delay": 10 } ], "other_directives": [ { "name": "host", "count": 1, "standard": false } ], "test": { "user_agent": "GPTBot", "path": "/admin/settings", "allowed": false, "matched_rule": { "type": "disallow", "path": "/", "line": 3 }, "matched_group": "specific", "matched_user_agents": [ "GPTBot" ], "reason": "matched_disallow" }, "ai_crawlers": [ { "user_agent": "GPTBot", "owner": "openai", "purpose": "training", "root_access": "disallowed", "group": "specific" }, { "user_agent": "OAI-SearchBot", "owner": "openai", "purpose": "search", "root_access": "partial", "group": "wildcard" }, { "user_agent": "ChatGPT-User", "owner": "openai", "purpose": "user_fetch", "root_access": "partial", "group": "wildcard" }, { "user_agent": "ClaudeBot", "owner": "anthropic", "purpose": "training", "root_access": "partial", "group": "wildcard" }, { "user_agent": "Claude-SearchBot", "owner": "anthropic", "purpose": "search", "root_access": "partial", "group": "wildcard" }, { "user_agent": "Claude-User", "owner": "anthropic", "purpose": "user_fetch", "root_access": "partial", "group": "wildcard" }, { "user_agent": "Google-Extended", "owner": "google", "purpose": "training_control", "root_access": "partial", "group": "wildcard" }, { "user_agent": "PerplexityBot", "owner": "perplexity", "purpose": "search", "root_access": "partial", "group": "wildcard" }, { "user_agent": "Perplexity-User", "owner": "perplexity", "purpose": "user_fetch", "root_access": "partial", "group": "wildcard" }, { "user_agent": "CCBot", "owner": "common_crawl", "purpose": "training", "root_access": "disallowed", "group": "specific" }, { "user_agent": "Bytespider", "owner": "bytedance", "purpose": "training", "root_access": "partial", "group": "wildcard" }, { "user_agent": "Applebot-Extended", "owner": "apple", "purpose": "training_control", "root_access": "partial", "group": "wildcard" }, { "user_agent": "meta-externalagent", "owner": "meta", "purpose": "training", "root_access": "partial", "group": "wildcard" }, { "user_agent": "Amazonbot", "owner": "amazon", "purpose": "search", "root_access": "partial", "group": "wildcard" } ], "issues": [ { "code": "crawl_delay_nonstandard", "count": 1, "lines": [ 8 ] }, { "code": "nonstandard_directive", "count": 1, "lines": [ 10 ] } ], "caveats": [], "summary": { "groups": 2, "rules": 3, "allow_rules": 1, "disallow_rules": 2, "sitemaps": 1, "issues": 2, "lines": 12, "ai_crawlers_allowed": 0, "ai_crawlers_disallowed": 2, "ai_crawlers_partial": 12, "ai_crawlers_unknown": 0, "ai_crawlers_with_specific_group": 2 }, "meta": { "cached": false, "duration_ms": 184, "source_version": "2026-10-09" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/sitemap-audit # XML sitemap audit API API Find and audit XML sitemaps with URL counts, lastmod freshness and protocol issues. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/sitemap-audit-api) ## Operations GET `/v1/sitemaps` [View API reference](https://domscan.net/docs/products/sitemap-audit#getSitemapAudit) ## GET `/v1/sitemaps` Operation: `getSitemapAudit` Credits and authentication: 2 Authentication required GET /v1/sitemaps Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | | sitemap | string | optional | | max_sitemaps | integer Default `5` | optional | #### Response fields | Field | Type | | --- | --- | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `url` | string | | `domain` | string | | `origin` | string | | `status` | string | | `checked_at` | string | | `fetch` | object | | `fetch.checked_url` | string | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string \| null | | `fetch.via_proxy` | boolean \| null | | `robots_txt` | object | | `robots_txt.status` | string | | `robots_txt.url` | string | | `robots_txt.http_status` | integer \| null | | `robots_txt.declared_sitemaps[]` | object[] | | `robots_txt.declared_sitemaps[]` | object | | `robots_txt.declared_sitemaps[].url` | string | | `robots_txt.declared_sitemaps[].same_site` | boolean | | `sitemaps[]` | object[] | | `sitemaps[]` | object | | `sitemaps[].url` | string | | `sitemaps[].source` | string | | `sitemaps[].parent` | string \| null | | `sitemaps[].status` | string | | `sitemaps[].http_status` | integer \| null | | `sitemaps[].final_url` | string \| null | | `sitemaps[].via_proxy` | boolean \| null | | `sitemaps[].content_type` | string \| null | | `sitemaps[].bytes` | integer \| null | | `sitemaps[].type` | string \| null | | `sitemaps[].url_count` | integer | | `sitemaps[].child_sitemap_count` | integer | | `sitemaps[].lastmod` | object | | `sitemaps[].lastmod.newest` | string \| null | | `sitemaps[].lastmod.oldest` | string \| null | | `sitemaps[].lastmod.with_lastmod_ratio` | number \| null | | `sitemaps[].extensions` | object | | `sitemaps[].extensions.images` | boolean | | `sitemaps[].extensions.videos` | boolean | | `sitemaps[].extensions.news` | boolean | | `sitemaps[].extensions.hreflang` | boolean | | `sitemaps[].counts` | object | | `sitemaps[].counts.invalid_loc` | integer | | `sitemaps[].counts.missing_loc` | integer | | `sitemaps[].counts.loc_too_long` | integer | | `sitemaps[].counts.cross_host_urls` | integer | | `sitemaps[].counts.protocol_mismatch_urls` | integer | | `sitemaps[].counts.duplicate_urls` | integer | | `sitemaps[].counts.invalid_lastmod` | integer | | `sitemaps[].counts.future_lastmod` | integer | | `sitemaps[].counts.cross_site_child_sitemaps` | integer | | `sitemaps[].issues[]` | string[] | | `sitemaps[].sample_urls[]` | string[] | | `totals` | object | | `totals.sitemaps_checked` | integer | | `totals.sitemaps_discovered` | integer | | `totals.urls_counted` | integer | | `totals.budget_exhausted` | boolean | | `freshness` | object | | `freshness.newest_lastmod` | string \| null | | `freshness.days_since_newest` | integer \| null | | `issues[]` | string[] | | `caveats[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/sitemaps?url=https%3A%2F%2Fexample.com&domain=example.com&sitemap=https%3A%2F%2Fexample.com%2Fsitemap_index.xml&max_sitemaps=5" ``` ```javascript const response = await fetch("https://domscan.net/v1/sitemaps?url=https%3A%2F%2Fexample.com&domain=example.com&sitemap=https%3A%2F%2Fexample.com%2Fsitemap_index.xml&max_sitemaps=5", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/sitemaps?url=https%3A%2F%2Fexample.com&domain=example.com&sitemap=https%3A%2F%2Fexample.com%2Fsitemap_index.xml&max_sitemaps=5", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/sitemaps?url=https%3A%2F%2Fexample.com&domain=example.com&sitemap=https%3A%2F%2Fexample.com%2Fsitemap_index.xml&max_sitemaps=5", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/sitemaps?url=https%3A%2F%2Fexample.com&domain=example.com&sitemap=https%3A%2F%2Fexample.com%2Fsitemap_index.xml&max_sitemaps=5") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "domain": "example.com", "origin": "https://example.com", "status": "found", "checked_at": "2026-10-09T12:00:00.000Z", "fetch": { "checked_url": "https://example.com/robots.txt", "http_status": 200, "final_url": "https://example.com/robots.txt", "via_proxy": true }, "robots_txt": { "status": "found", "url": "https://example.com/robots.txt", "http_status": 200, "declared_sitemaps": [ { "url": "https://example.com/sitemap_index.xml", "same_site": true }, { "url": "https://sitemaps.example.net/example.xml", "same_site": false } ] }, "sitemaps": [ { "url": "https://example.com/sitemap_index.xml", "source": "robots", "parent": null, "status": "ok", "http_status": 200, "final_url": "https://example.com/sitemap_index.xml", "via_proxy": true, "content_type": "application/xml; charset=utf-8", "bytes": 412, "type": "sitemapindex", "url_count": 0, "child_sitemap_count": 2, "lastmod": { "newest": "2026-10-01T00:00:00.000Z", "oldest": "2026-10-01T00:00:00.000Z", "with_lastmod_ratio": 1 }, "extensions": { "images": false, "videos": false, "news": false, "hreflang": false }, "counts": { "invalid_loc": 0, "missing_loc": 0, "loc_too_long": 0, "cross_host_urls": 0, "protocol_mismatch_urls": 0, "duplicate_urls": 0, "invalid_lastmod": 0, "future_lastmod": 0, "cross_site_child_sitemaps": 0 }, "issues": [], "sample_urls": [ "https://example.com/posts.xml", "https://example.com/pages.xml" ] }, { "url": "https://example.com/posts.xml", "source": "index_child", "parent": "https://example.com/sitemap_index.xml", "status": "ok", "http_status": 200, "final_url": "https://example.com/posts.xml", "via_proxy": true, "content_type": "application/xml", "bytes": 18234, "type": "urlset", "url_count": 120, "child_sitemap_count": 0, "lastmod": { "newest": "2026-10-05T00:00:00.000Z", "oldest": "2024-03-11T00:00:00.000Z", "with_lastmod_ratio": 0.975 }, "extensions": { "images": true, "videos": false, "news": false, "hreflang": true }, "counts": { "invalid_loc": 0, "missing_loc": 0, "loc_too_long": 0, "cross_host_urls": 0, "protocol_mismatch_urls": 2, "duplicate_urls": 1, "invalid_lastmod": 3, "future_lastmod": 0, "cross_site_child_sitemaps": 0 }, "issues": [ "protocol_mismatch", "duplicate_urls", "invalid_lastmod" ], "sample_urls": [ "https://example.com/blog/a", "https://example.com/blog/b", "https://example.com/blog/c", "http://example.com/blog/d", "https://example.com/blog/e" ] }, { "url": "https://example.com/pages.xml", "source": "index_child", "parent": "https://example.com/sitemap_index.xml", "status": "unknown", "http_status": 429, "final_url": "https://example.com/pages.xml", "via_proxy": true, "content_type": "text/html", "bytes": 162, "type": null, "url_count": 0, "child_sitemap_count": 0, "lastmod": { "newest": null, "oldest": null, "with_lastmod_ratio": null }, "extensions": { "images": false, "videos": false, "news": false, "hreflang": false }, "counts": { "invalid_loc": 0, "missing_loc": 0, "loc_too_long": 0, "cross_host_urls": 0, "protocol_mismatch_urls": 0, "duplicate_urls": 0, "invalid_lastmod": 0, "future_lastmod": 0, "cross_site_child_sitemaps": 0 }, "issues": [ "rate_limited" ], "sample_urls": [] } ], "totals": { "sitemaps_checked": 3, "sitemaps_discovered": 4, "urls_counted": 120, "budget_exhausted": false }, "freshness": { "newest_lastmod": "2026-10-05T00:00:00.000Z", "days_since_newest": 4 }, "issues": [ "cross_site_sitemap_declared", "protocol_mismatch", "duplicate_urls", "invalid_lastmod", "rate_limited" ], "caveats": [ "counts_cover_fetched_files_only", "cross_site_sitemaps_not_fetched" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/onpage # On-page SEO audit API API Audit titles, meta tags, headings, links, images and structured data with an SEO score. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/onpage-seo-api) ## Operations GET `/v1/onpage` [View API reference](https://domscan.net/docs/products/onpage#getOnPageAudit) ## GET `/v1/onpage` Operation: `getOnPageAudit` Credits and authentication: 2-6 Authentication required GET /v1/onpage Credits: 2-6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | render | boolean | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `fetch` | object | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer | | `fetch.truncated` | boolean | | `fetch.redirect_count` | integer | | `fetch.duration_ms` | integer | | `fetch.rendered` | boolean | | `score` | integer \| null | | `meta` | object | | `meta.title` | string \| null | | `meta.title_length` | integer | | `meta.description` | string \| null | | `meta.description_length` | integer | | `meta.canonical` | string \| null | | `meta.canonical_self_referencing` | boolean \| null | | `meta.canonical_header` | string \| null | | `meta.robots` | string \| null | | `meta.googlebot` | string \| null | | `meta.x_robots_tag` | string \| null | | `meta.indexable` | boolean | | `meta.googlebot_noindex` | boolean | | `meta.nofollow` | boolean | | `meta.meta_refresh` | string \| null | | `meta.duplicate_meta_tags[]` | string[] | | `meta.lang` | string \| null | | `meta.viewport` | string \| null | | `meta.favicon` | string \| null | | `meta.open_graph` | object | | `meta.open_graph.title` | string \| null | | `meta.open_graph.description` | string \| null | | `meta.open_graph.image` | string \| null | | `meta.open_graph.url` | string \| null | | `meta.open_graph.type` | string \| null | | `meta.twitter` | object | | `meta.twitter.card` | string \| null | | `meta.twitter.title` | string \| null | | `meta.twitter.description` | string \| null | | `meta.twitter.image` | string \| null | | `headings` | object | | `headings.h1[]` | string[] | | `headings.counts` | object | | `headings.counts.h1` | integer | | `headings.counts.h2` | integer | | `headings.counts.h3` | integer | | `headings.counts.h4` | integer | | `headings.counts.h5` | integer | | `headings.counts.h6` | integer | | `headings.outline[]` | object[] | | `headings.outline[]` | object | | `headings.outline[].level` | integer | | `headings.outline[].text` | string | | `content` | object | | `content.word_count` | integer | | `content.text_bytes` | integer | | `content.html_bytes` | integer | | `content.text_to_html_ratio` | number | | `links` | object | | `links.total` | integer | | `links.internal` | integer | | `links.external` | integer | | `links.nofollow` | integer | | `links.empty_anchor` | integer | | `links.unresolvable` | integer | | `images` | object | | `images.total` | integer | | `images.missing_alt` | integer | | `images.empty_alt` | integer | | `images.missing_dimensions` | integer | | `images.lazy_loaded` | integer | | `resources` | object | | `resources.scripts` | integer | | `resources.inline_scripts` | integer | | `resources.stylesheets` | integer | | `resources.iframes` | integer | | `resources.mixed_content` | integer | | `resources.render_blocking_scripts` | integer \| null | | `resources.render_blocking_stylesheets` | integer \| null | | `structured_data` | object | | `structured_data.json_ld` | integer | | `structured_data.microdata` | integer | | `structured_data.rdfa` | integer | | `structured_data.types[]` | string[] | | `hreflang` | object | | `hreflang.count` | integer | | `checks[]` | object[] | | `checks[]` | object | | `checks[].id` | string | | `checks[].status` | string | | `checks[].severity` | string | | `checks[].value` | unknown | | `issues[]` | string[] | | `caveats[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/onpage?url=https%3A%2F%2Fexample.com&render=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/onpage?url=https%3A%2F%2Fexample.com&render=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/onpage?url=https%3A%2F%2Fexample.com&render=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/onpage?url=https%3A%2F%2Fexample.com&render=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/onpage?url=https%3A%2F%2Fexample.com&render=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/shoes/trail-runner", "final_url": "https://example.com/shoes/trail-runner", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 3535, "truncated": false, "redirect_count": 0, "duration_ms": 412, "rendered": false }, "score": 87, "meta": { "title": "Trail Running Shoes for Rocky Terrain | Example Outdoor", "title_length": 55, "description": "Lightweight trail running shoes with a grippy outsole, rock plate and breathable mesh. Free returns within 30 days on every pair.", "description_length": 129, "canonical": "https://example.com/shoes/trail-runner", "canonical_self_referencing": true, "canonical_header": null, "robots": "index, follow", "googlebot": null, "x_robots_tag": null, "indexable": true, "googlebot_noindex": false, "nofollow": false, "meta_refresh": null, "duplicate_meta_tags": [], "lang": "en", "viewport": "width=device-width, initial-scale=1", "favicon": "/favicon.ico", "open_graph": { "title": "Trail Running Shoes for Rocky Terrain", "description": null, "image": "https://example.com/images/trail-runner.jpg", "url": null, "type": null }, "twitter": { "card": "summary_large_image", "title": null, "description": null, "image": null } }, "headings": { "h1": [ "Trail Running Shoes for Rocky Terrain" ], "counts": { "h1": 1, "h2": 1, "h3": 0, "h4": 1, "h5": 0, "h6": 0 }, "outline": [ { "level": 1, "text": "Trail Running Shoes for Rocky Terrain" }, { "level": 2, "text": "Why runners choose these trail running shoes" }, { "level": 4, "text": "Sizing" } ] }, "content": { "word_count": 122, "text_bytes": 780, "html_bytes": 3535, "text_to_html_ratio": 0.221 }, "links": { "total": 7, "internal": 5, "external": 2, "nofollow": 1, "empty_anchor": 1, "unresolvable": 0 }, "images": { "total": 3, "missing_alt": 1, "empty_alt": 0, "missing_dimensions": 2, "lazy_loaded": 0 }, "resources": { "scripts": 1, "inline_scripts": 0, "stylesheets": 1, "iframes": 0, "mixed_content": 1, "render_blocking_scripts": 0, "render_blocking_stylesheets": 1 }, "structured_data": { "json_ld": 2, "microdata": 1, "rdfa": 0, "types": [ "AggregateRating", "Brand", "BreadcrumbList", "ListItem", "Offer", "Product", "Rating", "Review" ] }, "hreflang": { "count": 3 }, "checks": [ { "id": "mixed_content", "status": "fail", "severity": "high", "value": 1 }, { "id": "heading_hierarchy", "status": "warn", "severity": "low", "value": 1 }, { "id": "word_count", "status": "warn", "severity": "medium", "value": 122 }, { "id": "images_alt", "status": "warn", "severity": "medium", "value": 1 }, { "id": "title_present", "status": "pass", "severity": "high" }, { "id": "h1_present", "status": "pass", "severity": "high", "value": 1 }, { "id": "render_blocking_resources", "status": "warn", "severity": "low", "value": 1 } ], "issues": [ "mixed_content", "heading_hierarchy", "word_count", "images_alt", "images_dimensions", "empty_anchor_text", "render_blocking_resources" ], "caveats": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/javascript-seo # JavaScript SEO rendering check API API Compare raw and rendered HTML to see which SEO signals depend on JavaScript. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/javascript-seo-api) ## Operations GET `/v1/onpage/render-diff` [View API reference](https://domscan.net/docs/products/javascript-seo#getRenderDiff) ## GET `/v1/onpage/render-diff` Operation: `getRenderDiff` Credits and authentication: 7 Authentication required GET /v1/onpage/render-diff Credits: 7 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `raw` | object | | `raw.fetch` | object | | `raw.fetch.http_status` | integer \| null | | `raw.fetch.final_url` | string | | `raw.fetch.content_type` | string \| null | | `raw.fetch.bytes` | integer | | `raw.fetch.truncated` | boolean | | `raw.fetch.redirect_count` | integer | | `raw.fetch.duration_ms` | integer | | `raw.fetch.rendered` | boolean | | `raw.signals` | object | | `raw.signals.title` | string \| null | | `raw.signals.meta_description` | string \| null | | `raw.signals.canonical` | string \| null | | `raw.signals.robots` | string \| null | | `raw.signals.noindex` | boolean | | `raw.signals.h1[]` | string[] | | `raw.signals.word_count` | integer | | `raw.signals.internal_links` | integer | | `raw.signals.external_links` | integer | | `raw.signals.structured_data_types[]` | string[] | | `raw.signals.hreflang_count` | integer | | `raw.signals.lang` | string \| null | | `rendered` | object | | `rendered.fetch` | object | | `rendered.fetch.http_status` | integer \| null | | `rendered.fetch.final_url` | string | | `rendered.fetch.content_type` | string \| null | | `rendered.fetch.bytes` | integer | | `rendered.fetch.truncated` | boolean | | `rendered.fetch.redirect_count` | integer | | `rendered.fetch.duration_ms` | integer | | `rendered.fetch.rendered` | boolean | | `rendered.signals` | object | | `rendered.signals.title` | string \| null | | `rendered.signals.meta_description` | string \| null | | `rendered.signals.canonical` | string \| null | | `rendered.signals.robots` | string \| null | | `rendered.signals.noindex` | boolean | | `rendered.signals.h1[]` | string[] | | `rendered.signals.word_count` | integer | | `rendered.signals.internal_links` | integer | | `rendered.signals.external_links` | integer | | `rendered.signals.structured_data_types[]` | string[] | | `rendered.signals.hreflang_count` | integer | | `rendered.signals.lang` | string \| null | | `js_dependence` | string \| null | | `rendered_word_share` | number \| null | | `differences[]` | object[] | | `differences[]` | object | | `differences[].field` | string | | `differences[].change` | string | | `differences[].impact` | string | | `differences[].raw` | unknown | | `differences[].rendered` | unknown | | `issues[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/onpage/render-diff?url=https%3A%2F%2Fexample.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/onpage/render-diff?url=https%3A%2F%2Fexample.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/onpage/render-diff?url=https%3A%2F%2Fexample.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/onpage/render-diff?url=https%3A%2F%2Fexample.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/onpage/render-diff?url=https%3A%2F%2Fexample.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/shoes/trail-runner", "final_url": "https://example.com/shoes/trail-runner", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "raw": { "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 183, "truncated": false, "redirect_count": 0, "duration_ms": 380, "rendered": false }, "signals": { "title": "Example Outdoor", "meta_description": null, "canonical": null, "robots": "noindex", "noindex": true, "h1": [], "word_count": 0, "internal_links": 0, "external_links": 0, "structured_data_types": [], "hreflang_count": 0, "lang": "en" } }, "rendered": { "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 3535, "truncated": false, "redirect_count": 0, "duration_ms": 4210, "rendered": true }, "signals": { "title": "Trail Running Shoes for Rocky Terrain | Example Outdoor", "meta_description": "Lightweight trail running shoes with a grippy outsole, rock plate and breathable mesh. Free returns within 30 days on every pair.", "canonical": "https://example.com/shoes/trail-runner", "robots": "index, follow", "noindex": false, "h1": [ "Trail Running Shoes for Rocky Terrain" ], "word_count": 122, "internal_links": 5, "external_links": 2, "structured_data_types": [ "AggregateRating", "Brand", "BreadcrumbList", "ListItem", "Offer", "Product", "Rating", "Review" ], "hreflang_count": 3, "lang": "en" } }, "js_dependence": "high", "rendered_word_share": 1, "differences": [ { "field": "title", "change": "changed_by_js", "impact": "high", "raw": "Example Outdoor", "rendered": "Trail Running Shoes for Rocky Terrain | Example Outdoor" }, { "field": "meta_description", "change": "added_by_js", "impact": "medium", "raw": null, "rendered": "Lightweight trail running shoes with a grippy outsole, rock plate and breathable mesh. Free returns within 30 days on every pair." }, { "field": "canonical", "change": "added_by_js", "impact": "high", "raw": null, "rendered": "https://example.com/shoes/trail-runner" }, { "field": "robots", "change": "changed_by_js", "impact": "high", "raw": "noindex", "rendered": "index, follow" }, { "field": "noindex", "change": "removed_by_js", "impact": "high", "raw": true, "rendered": false } ], "issues": [ "robots_changed_by_js", "canonical_changed_by_js", "h1_requires_js", "content_requires_js", "links_require_js", "structured_data_changed_by_js" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/structured-data # Structured data validation API API Extract and validate JSON-LD, Microdata and RDFa schema.org markup. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/structured-data-api) ## Operations GET `/v1/structured-data` [View API reference](https://domscan.net/docs/products/structured-data#getStructuredData) ## GET `/v1/structured-data` Operation: `getStructuredData` Credits and authentication: 2-6 Authentication required GET /v1/structured-data Credits: 2-6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | render | boolean | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `fetch` | object | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer | | `fetch.truncated` | boolean | | `fetch.redirect_count` | integer | | `fetch.duration_ms` | integer | | `fetch.rendered` | boolean | | `summary` | object | | `summary.json_ld` | integer | | `summary.microdata` | integer | | `summary.rdfa` | integer | | `summary.total_items` | integer | | `summary.valid_items` | integer | | `summary.errors` | integer | | `summary.warnings` | integer | | `types[]` | string[] | | `block_errors[]` | string[] | | `items[]` | object[] | | `items[]` | object | | `items[].format` | string | | `items[].types[]` | string[] | | `items[].properties[]` | string[] | | `items[].values` | object | | `items[].children[]` | object[] | | `items[].children[]` | object | | `items[].children[].format` | string | | `items[].children[].types[]` | string[] | | `items[].children[].properties[]` | string[] | | `items[].children[].values` | object | | `items[].children[].children[]` | object[] | | `items[].children[].children[]` | object | | `items[].children[].path` | string | | `items[].children[].status` | string | | `items[].children[].errors[]` | object[] | | `items[].children[].errors[]` | object | | `items[].children[].errors[].code` | string | | `items[].children[].errors[].property` | string | | `items[].children[].warnings[]` | object[] | | `items[].children[].warnings[]` | object | | `items[].children[].warnings[].code` | string | | `items[].children[].warnings[].property` | string | | `items[].path` | string | | `items[].status` | string | | `items[].errors[]` | object[] | | `items[].errors[]` | object | | `items[].errors[].code` | string | | `items[].errors[].property` | string | | `items[].warnings[]` | object[] | | `items[].warnings[]` | object | | `items[].warnings[].code` | string | | `items[].warnings[].property` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/structured-data?url=https%3A%2F%2Fexample.com&render=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/structured-data?url=https%3A%2F%2Fexample.com&render=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/structured-data?url=https%3A%2F%2Fexample.com&render=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/structured-data?url=https%3A%2F%2Fexample.com&render=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/structured-data?url=https%3A%2F%2Fexample.com&render=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/shoes/trail-runner", "final_url": "https://example.com/shoes/trail-runner", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 3535, "truncated": false, "redirect_count": 0, "duration_ms": 412, "rendered": false }, "summary": { "json_ld": 2, "microdata": 1, "rdfa": 0, "total_items": 9, "valid_items": 3, "errors": 1, "warnings": 5 }, "types": [ "AggregateRating", "Brand", "BreadcrumbList", "ListItem", "Offer", "Product", "Rating", "Review" ], "block_errors": [], "items": [ { "format": "json-ld", "types": [ "Product" ], "properties": [ "name", "image", "sku", "brand", "offers", "aggregateRating" ], "values": { "name": "Trail Runner 2", "image": "https://example.com/images/trail-runner.jpg", "sku": "TR-2" }, "children": [ { "format": "json-ld", "types": [ "Brand" ], "properties": [ "name" ], "values": { "name": "Example Outdoor" }, "children": [], "path": "json_ld[0].children[0]", "status": "unchecked", "errors": [], "warnings": [] }, { "format": "json-ld", "types": [ "Offer" ], "properties": [ "price", "priceCurrency", "availability" ], "values": { "price": "129.00", "priceCurrency": "EUR", "availability": "https://schema.org/InStock" }, "children": [], "path": "json_ld[0].children[1]", "status": "warnings", "errors": [], "warnings": [ { "code": "missing_recommended", "property": "url" } ] }, { "format": "json-ld", "types": [ "AggregateRating" ], "properties": [ "ratingValue", "reviewCount" ], "values": { "ratingValue": "4.6", "reviewCount": "87" }, "children": [], "path": "json_ld[0].children[2]", "status": "warnings", "errors": [], "warnings": [ { "code": "missing_recommended", "property": "bestRating" } ] } ], "path": "json_ld[0]", "status": "warnings", "errors": [], "warnings": [ { "code": "missing_recommended", "property": "description" } ] }, { "format": "json-ld", "types": [ "BreadcrumbList" ], "properties": [ "itemListElement" ], "values": {}, "children": [ { "format": "json-ld", "types": [ "ListItem" ], "properties": [ "position", "name", "item" ], "values": { "position": "1", "name": "Shoes", "item": "https://example.com/shoes" }, "children": [], "path": "json_ld[1].children[0]", "status": "valid", "errors": [], "warnings": [] }, { "format": "json-ld", "types": [ "ListItem" ], "properties": [ "name" ], "values": { "name": "Trail Runner 2" }, "children": [], "path": "json_ld[1].children[1]", "status": "errors", "errors": [ { "code": "missing_required", "property": "position" } ], "warnings": [ { "code": "missing_recommended", "property": "item" } ] } ], "path": "json_ld[1]", "status": "valid", "errors": [], "warnings": [] } ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/keyword-density # Keyword density API API Find the most frequent keywords and phrases on a page with density percentages. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/keyword-density-api) ## Operations GET `/v1/keyword-density` [View API reference](https://domscan.net/docs/products/keyword-density#getKeywordDensity) ## GET `/v1/keyword-density` Operation: `getKeywordDensity` Credits and authentication: 2-6 Authentication required GET /v1/keyword-density Credits: 2-6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | render | boolean | optional | | keywords | string | optional | | top | integer Default `20` | optional | | include_stopwords | boolean | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `fetch` | object | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer | | `fetch.truncated` | boolean | | `fetch.redirect_count` | integer | | `fetch.duration_ms` | integer | | `fetch.rendered` | boolean | | `language` | string \| null | | `total_words` | integer | | `unique_words` | integer | | `stopwords_removed` | boolean | | `keywords` | object | | `keywords.one_word[]` | object[] | | `keywords.one_word[]` | object | | `keywords.one_word[].keyword` | string | | `keywords.one_word[].count` | integer | | `keywords.one_word[].density` | number | | `keywords.two_words[]` | object[] | | `keywords.two_words[]` | object | | `keywords.two_words[].keyword` | string | | `keywords.two_words[].count` | integer | | `keywords.two_words[].density` | number | | `keywords.three_words[]` | object[] | | `keywords.three_words[]` | object | | `keywords.three_words[].keyword` | string | | `keywords.three_words[].count` | integer | | `keywords.three_words[].density` | number | | `targets[]` | object[] | | `targets[]` | object | | `targets[].keyword` | string | | `targets[].count` | integer | | `targets[].density` | number | | `targets[].in_title` | boolean | | `targets[].in_meta_description` | boolean | | `targets[].in_h1` | boolean | | `targets[].in_headings` | boolean | | `targets[].in_url` | boolean | | `targets[].in_first_100_words` | boolean | | `caveats[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/keyword-density?url=https%3A%2F%2Fexample.com&render=false&keywords=launch%2Cgrid&top=20&include_stopwords=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/keyword-density?url=https%3A%2F%2Fexample.com&render=false&keywords=launch%2Cgrid&top=20&include_stopwords=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/keyword-density?url=https%3A%2F%2Fexample.com&render=false&keywords=launch%2Cgrid&top=20&include_stopwords=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/keyword-density?url=https%3A%2F%2Fexample.com&render=false&keywords=launch%2Cgrid&top=20&include_stopwords=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/keyword-density?url=https%3A%2F%2Fexample.com&render=false&keywords=launch%2Cgrid&top=20&include_stopwords=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/shoes/trail-runner", "final_url": "https://example.com/shoes/trail-runner", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 3535, "truncated": false, "redirect_count": 0, "duration_ms": 412, "rendered": false }, "language": "en", "total_words": 122, "unique_words": 86, "stopwords_removed": true, "keywords": { "one_word": [ { "keyword": "shoes", "count": 5, "density": 4.1 }, { "keyword": "trail", "count": 5, "density": 4.1 }, { "keyword": "running", "count": 5, "density": 4.1 } ], "two_words": [ { "keyword": "trail running", "count": 5, "density": 4.1 }, { "keyword": "running shoes", "count": 4, "density": 3.28 }, { "keyword": "rocky terrain", "count": 3, "density": 2.46 } ], "three_words": [ { "keyword": "trail running shoes", "count": 4, "density": 3.28 } ] }, "targets": [ { "keyword": "trail running shoes", "count": 4, "density": 3.28, "in_title": true, "in_meta_description": true, "in_h1": true, "in_headings": true, "in_url": false, "in_first_100_words": true } ], "caveats": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/page-links # Page links and broken link checker API API List page links and find broken ones with bounded status checks. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/link-checker-api) ## Operations GET `/v1/links` [View API reference](https://domscan.net/docs/products/page-links#getPageLinks) ## GET `/v1/links` Operation: `getPageLinks` Credits and authentication: 2-6 Authentication required GET /v1/links Credits: 2-6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | render | boolean | optional | | check | boolean | optional | | type | string Allowed values `all`, `internal`, `external` Default `all` | optional | | limit | integer Default `200` | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `fetch` | object | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer | | `fetch.truncated` | boolean | | `fetch.redirect_count` | integer | | `fetch.duration_ms` | integer | | `fetch.rendered` | boolean | | `summary` | object | | `summary.total` | integer | | `summary.internal` | integer | | `summary.external` | integer | | `summary.nofollow` | integer | | `summary.empty_anchor` | integer | | `summary.unique_urls` | integer | | `summary.external_domains` | integer | | `links[]` | object[] | | `links[]` | object | | `links[].url` | string | | `links[].text` | string | | `links[].type` | string | | `links[].rel[]` | string[] | | `links[].nofollow` | boolean | | `links[].image_alt` | string \| null | | `has_more` | boolean | | `check` | object | | `check.unique_targets` | integer | | `check.checked` | integer | | `check.not_checked` | integer | | `check.ok` | integer | | `check.redirect` | integer | | `check.broken` | integer | | `check.unknown` | integer | | `check.unchecked` | integer | | `check.skipped` | integer | | `check.results[]` | object[] | | `check.results[]` | object | | `check.results[].url` | string | | `check.results[].state` | string | | `check.results[].http_status` | integer \| null | | `check.results[].final_url` | string \| null | | `check.results[].redirect_count` | integer | | `check.results[].reason` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/links?url=https%3A%2F%2Fexample.com&render=false&check=false&type=all&limit=25" ``` ```javascript const response = await fetch("https://domscan.net/v1/links?url=https%3A%2F%2Fexample.com&render=false&check=false&type=all&limit=25", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/links?url=https%3A%2F%2Fexample.com&render=false&check=false&type=all&limit=25", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/links?url=https%3A%2F%2Fexample.com&render=false&check=false&type=all&limit=25", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/links?url=https%3A%2F%2Fexample.com&render=false&check=false&type=all&limit=25") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/shoes/trail-runner", "final_url": "https://example.com/shoes/trail-runner", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 3535, "truncated": false, "redirect_count": 0, "duration_ms": 412, "rendered": false }, "summary": { "total": 7, "internal": 5, "external": 2, "nofollow": 1, "empty_anchor": 1, "unique_urls": 7, "external_domains": 2 }, "links": [ { "url": "https://example.com/", "text": "Home", "type": "internal", "rel": [], "nofollow": false, "image_alt": null }, { "url": "https://example.com/shoes", "text": "Shoes", "type": "internal", "rel": [], "nofollow": false, "image_alt": null }, { "url": "https://example.com/missing-page", "text": "Old sale", "type": "internal", "rel": [], "nofollow": false, "image_alt": null } ], "has_more": true, "check": { "unique_targets": 7, "checked": 7, "not_checked": 0, "ok": 4, "redirect": 1, "broken": 1, "unknown": 1, "unchecked": 0, "skipped": 0, "results": [ { "url": "https://example.com/", "http_status": 200, "final_url": "https://example.com/", "redirect_count": 0, "state": "ok", "reason": null }, { "url": "https://example.com/shoes", "http_status": 200, "final_url": "https://example.com/shoes", "redirect_count": 1, "state": "redirect", "reason": null }, { "url": "https://example.com/missing-page", "http_status": 404, "final_url": "https://example.com/missing-page", "redirect_count": 0, "state": "broken", "reason": "http_404" }, { "url": "https://partner.example.org/fit-guide", "http_status": 403, "final_url": "https://partner.example.org/fit-guide", "redirect_count": 0, "state": "unknown", "reason": "blocked" } ] } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/hreflang # Hreflang validation API API Validate hreflang codes, x-default, self references and return links. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/hreflang-api) ## Operations GET `/v1/hreflang` [View API reference](https://domscan.net/docs/products/hreflang#getHreflangAudit) ## GET `/v1/hreflang` Operation: `getHreflangAudit` Credits and authentication: 3 Authentication required GET /v1/hreflang Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | max_alternates | integer Default `10` | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `fetch` | object | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer | | `fetch.truncated` | boolean | | `fetch.redirect_count` | integer | | `fetch.duration_ms` | integer | | `fetch.rendered` | boolean | | `lang` | string \| null | | `entries[]` | object[] | | `entries[]` | object | | `entries[].hreflang` | string | | `entries[].href` | string | | `entries[].url` | string \| null | | `entries[].source` | string | | `entries[].valid_code` | boolean | | `entries[].issues[]` | string[] | | `self_reference` | boolean | | `x_default` | boolean | | `issues[]` | string[] | | `return_links` | object | | `return_links.alternates` | integer | | `return_links.checked` | integer | | `return_links.not_checked` | integer | | `return_links.confirmed` | integer | | `return_links.missing` | integer | | `return_links.code_mismatch` | integer | | `return_links.not_found` | integer | | `return_links.unknown` | integer | | `return_links.results[]` | object[] | | `return_links.results[]` | object | | `return_links.results[].url` | string | | `return_links.results[].hreflang[]` | string[] | | `return_links.results[].state` | string | | `return_links.results[].http_status` | integer \| null | | `return_links.results[].final_url` | string \| null | | `return_links.results[].canonical` | string \| null | | `return_links.results[].lang` | string \| null | | `return_links.results[].issues[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/hreflang?url=https%3A%2F%2Fexample.com&max_alternates=10" ``` ```javascript const response = await fetch("https://domscan.net/v1/hreflang?url=https%3A%2F%2Fexample.com&max_alternates=10", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/hreflang?url=https%3A%2F%2Fexample.com&max_alternates=10", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/hreflang?url=https%3A%2F%2Fexample.com&max_alternates=10", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/hreflang?url=https%3A%2F%2Fexample.com&max_alternates=10") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/shoes/trail-runner", "final_url": "https://example.com/shoes/trail-runner", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "fetch": { "http_status": 200, "final_url": "https://example.com/shoes/trail-runner", "content_type": "text/html", "bytes": 3535, "truncated": false, "redirect_count": 0, "duration_ms": 412, "rendered": false }, "lang": "en", "entries": [ { "hreflang": "en", "href": "https://example.com/shoes/trail-runner", "url": "https://example.com/shoes/trail-runner", "source": "html", "valid_code": true, "issues": [] }, { "hreflang": "es-ES", "href": "https://example.com/es/zapatillas/trail-runner", "url": "https://example.com/es/zapatillas/trail-runner", "source": "html", "valid_code": true, "issues": [] }, { "hreflang": "x-default", "href": "https://example.com/shoes/trail-runner", "url": "https://example.com/shoes/trail-runner", "source": "html", "valid_code": true, "issues": [] } ], "self_reference": true, "x_default": true, "issues": [], "return_links": { "alternates": 1, "checked": 1, "not_checked": 0, "confirmed": 1, "missing": 0, "not_found": 0, "unknown": 0, "results": [ { "url": "https://example.com/es/zapatillas/trail-runner", "hreflang": [ "es-ES" ], "http_status": 200, "final_url": "https://example.com/es/zapatillas/trail-runner", "canonical": "https://example.com/es/zapatillas/trail-runner", "lang": "es", "issues": [], "state": "confirmed" } ] } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/robots-txt-tester # Robots.txt Tester API API Test many URLs and crawlers against a pasted or live robots.txt. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/robots-txt-tester-api) ## Operations POST `/v1/robots/test` [View API reference](https://domscan.net/docs/products/robots-txt-tester#testRobotsTxt) ## POST `/v1/robots/test` Operation: `testRobotsTxt` Credits and authentication: 1 Authentication required POST /v1/robots/test Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | robots_txt | string | optional | | url | string | optional | | urls | string[] | required | | user_agents | string[] | optional | #### Response fields | Field | Type | | --- | --- | | `source` | string | | `url` | string \| null | | `robots_url` | string \| null | | `status` | string | | `checked_at` | string | | `summary` | object | | `summary.tests` | integer | | `summary.allowed` | integer | | `summary.disallowed` | integer | | `summary.unknown` | integer | | `summary.groups` | integer | | `summary.rules` | integer | | `summary.issues` | integer | | `user_agents[]` | object[] | | `user_agents[]` | object | | `user_agents[].user_agent` | string | | `user_agents[].allowed` | integer | | `user_agents[].disallowed` | integer | | `user_agents[].unknown` | integer | | `results[]` | object[] | | `results[]` | object | | `results[].url` | string | | `results[].path` | string | | `results[].user_agent` | string | | `results[].token` | string | | `results[].allowed` | boolean \| null | | `results[].reason` | string | | `results[].matched_rule` | object | | `results[].matched_rule.type` | string | | `results[].matched_rule.path` | string | | `results[].matched_rule.line` | integer | | `results[].matched_group` | string \| null | | `results[].matched_user_agents[]` | string[] | | `results[].vendor` | object | | `results[].vendor.allowed` | boolean \| null | | `results[].vendor.reason` | string | | `results[].vendor.matched_rule` | object | | `results[].vendor.matched_rule.type` | string | | `results[].vendor.matched_rule.path` | string | | `results[].vendor.matched_rule.line` | integer | | `results[].vendor.matched_group` | string | | `sitemaps[]` | string[] | | `issues[]` | object[] | | `issues[]` | object | | `issues[].code` | string | | `issues[].count` | integer | | `issues[].lines[]` | integer[] | | `caveats[]` | string[] | | `fetch` | object | | `fetch.checked_url` | string | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string \| null | | `fetch.via_proxy` | boolean \| null | | `fetch.redirect_count` | integer \| null | | `fetch.content_type` | string \| null | | `fetch.bytes` | integer \| null | | `fetch.truncated` | boolean | | `fetch.error` | string \| null | | `meta` | object | | `meta.cached` | boolean | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/robots/test" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "robots_txt": "User-agent: GPTBot\nDisallow: /\n\nUser-agent: *\nDisallow: /admin/\nAllow: /admin/public", "urls": [ "/blog/post-1", "/admin/public" ], "user_agents": [ "Googlebot", "GPTBot" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/robots/test", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "robots_txt": "User-agent: GPTBot\nDisallow: /\n\nUser-agent: *\nDisallow: /admin/\nAllow: /admin/public", "urls": [ "/blog/post-1", "/admin/public" ], "user_agents": [ "Googlebot", "GPTBot" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/robots/test", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "robots_txt": "User-agent: GPTBot\nDisallow: /\n\nUser-agent: *\nDisallow: /admin/\nAllow: /admin/public", "urls": [ "/blog/post-1", "/admin/public", ], "user_agents": [ "Googlebot", "GPTBot", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "robots_txt": "User-agent: GPTBot\nDisallow: /\n\nUser-agent: *\nDisallow: /admin/\nAllow: /admin/public", "urls": [ "/blog/post-1", "/admin/public" ], "user_agents": [ "Googlebot", "GPTBot" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/robots/test", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/robots/test") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "robots_txt" => "User-agent: GPTBot\nDisallow: /\n\nUser-agent: *\nDisallow: /admin/\nAllow: /admin/public", "urls" => [ "/blog/post-1", "/admin/public" ], "user_agents" => [ "Googlebot", "GPTBot" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "source": "provided", "url": null, "robots_url": null, "status": "found", "checked_at": "2026-10-13T10:00:00.000Z", "summary": { "tests": 4, "allowed": 2, "disallowed": 2, "unknown": 0, "groups": 2, "rules": 3, "issues": 0 }, "user_agents": [ { "user_agent": "Googlebot", "allowed": 2, "disallowed": 0, "unknown": 0 }, { "user_agent": "GPTBot", "allowed": 0, "disallowed": 2, "unknown": 0 } ], "results": [ { "url": "/blog/post-1", "path": "/blog/post-1", "user_agent": "Googlebot", "token": "Googlebot", "allowed": true, "reason": "no_matching_rule", "matched_rule": null, "matched_group": "wildcard", "matched_user_agents": [ "*" ], "vendor": null }, { "url": "/admin/public", "path": "/admin/public", "user_agent": "Googlebot", "token": "Googlebot", "allowed": true, "reason": "matched_allow", "matched_rule": { "type": "allow", "path": "/admin/public", "line": 6 }, "matched_group": "wildcard", "matched_user_agents": [ "*" ], "vendor": null }, { "url": "/blog/post-1", "path": "/blog/post-1", "user_agent": "GPTBot", "token": "GPTBot", "allowed": false, "reason": "matched_disallow", "matched_rule": { "type": "disallow", "path": "/", "line": 2 }, "matched_group": "specific", "matched_user_agents": [ "GPTBot" ], "vendor": null }, { "url": "/admin/public", "path": "/admin/public", "user_agent": "GPTBot", "token": "GPTBot", "allowed": false, "reason": "matched_disallow", "matched_rule": { "type": "disallow", "path": "/", "line": 2 }, "matched_group": "specific", "matched_user_agents": [ "GPTBot" ], "vendor": null } ], "sitemaps": [], "issues": [], "caveats": [], "fetch": null, "meta": { "cached": false, "duration_ms": 2 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/ads-txt # ads.txt and sellers.json validation API API Validate ads.txt and app-ads.txt records and confirm sellers against sellers.json. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/ads-txt-api) ## Operations GET `/v1/ads-txt` [View API reference](https://domscan.net/docs/products/ads-txt#getAdsTxt) ## GET `/v1/ads-txt` Operation: `getAdsTxt` Credits and authentication: 2-5 Authentication required GET /v1/ads-txt Credits: 2-5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | file | string Allowed values `ads.txt`, `app-ads.txt` Default `ads.txt` | optional | | verify_sellers | boolean | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `file` | string | | `url` | string | | `checked_at` | string | | `status` | string | | `reason` | string \| null | | `fetch` | object | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string \| null | | `fetch.bytes` | integer | | `fetch.truncated` | boolean | | `summary` | object | | `summary.records` | integer | | `summary.direct` | integer | | `summary.reseller` | integer | | `summary.ad_systems` | integer | | `summary.records_truncated` | boolean | | `summary.no_authorized_sellers` | boolean | | `variables` | object | | `records[]` | object[] | | `records[]` | object | | `records[].line` | integer | | `records[].ad_system` | string | | `records[].account_id` | string | | `records[].relationship` | string | | `records[].certification_authority_id` | string \| null | | `issues[]` | object[] | | `issues[]` | object | | `issues[].code` | string | | `issues[].count` | integer | | `issues[].lines[]` | integer[] | | `sellers` | object | | `sellers.systems_total` | integer | | `sellers.systems_checked` | integer | | `sellers.confirmed` | integer | | `sellers.confidential` | integer | | `sellers.type_mismatch` | integer | | `sellers.seller_not_found` | integer | | `sellers.unknown` | integer | | `sellers.systems[]` | object[] | | `sellers.systems[]` | object | | `sellers.systems[].ad_system` | string | | `sellers.systems[].sellers_json` | string | | `sellers.systems[].reason` | string \| null | | `sellers.systems[].records_checked` | integer | | `sellers.results[]` | object[] | | `sellers.results[]` | object | | `sellers.results[].ad_system` | string | | `sellers.results[].account_id` | string | | `sellers.results[].relationship` | string | | `sellers.results[].state` | string | | `sellers.results[].seller_type` | string \| null | | `sellers.results[].seller_name` | string \| null | | `sellers.results[].seller_domain` | string \| null | | `sellers.results[].match` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ads-txt?url=https%3A%2F%2Fexample.com&file=ads.txt&verify_sellers=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/ads-txt?url=https%3A%2F%2Fexample.com&file=ads.txt&verify_sellers=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ads-txt?url=https%3A%2F%2Fexample.com&file=ads.txt&verify_sellers=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ads-txt?url=https%3A%2F%2Fexample.com&file=ads.txt&verify_sellers=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ads-txt?url=https%3A%2F%2Fexample.com&file=ads.txt&verify_sellers=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "file": "ads.txt", "url": "https://example.com/ads.txt", "checked_at": "2026-10-13T12:00:00.000Z", "status": "found", "reason": null, "fetch": { "http_status": 200, "final_url": "https://example.com/ads.txt", "bytes": 20603, "truncated": false }, "summary": { "records": 2, "direct": 1, "reseller": 1, "ad_systems": 2, "records_truncated": false, "no_authorized_sellers": false }, "variables": { "ownerdomain": [ "example.com" ] }, "records": [ { "line": 3, "ad_system": "google.com", "account_id": "pub-1234567890", "relationship": "DIRECT", "certification_authority_id": "f08c47fec0942fa0" }, { "line": 4, "ad_system": "openx.com", "account_id": "537120563", "relationship": "RESELLER", "certification_authority_id": null } ], "issues": [ { "code": "duplicate_record", "count": 1, "lines": [ 9 ] } ], "sellers": { "systems_total": 2, "systems_checked": 2, "confirmed": 1, "confidential": 0, "type_mismatch": 0, "seller_not_found": 0, "unknown": 1, "systems": [ { "ad_system": "google.com", "sellers_json": "unknown", "reason": "too_large", "records_checked": 1 }, { "ad_system": "openx.com", "sellers_json": "ok", "reason": null, "records_checked": 1 } ], "results": [ { "ad_system": "google.com", "account_id": "pub-1234567890", "relationship": "DIRECT", "state": "unknown", "seller_type": null, "seller_name": null, "seller_domain": null, "match": null }, { "ad_system": "openx.com", "account_id": "537120563", "relationship": "RESELLER", "state": "confirmed", "seller_type": "INTERMEDIARY", "seller_name": "Example Exchange", "seller_domain": "exchange.example", "match": "exact" } ] } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/duplicate-content # Duplicate content checker API API Compare pages for duplicate content, titles and meta descriptions. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/duplicate-content-api) ## Operations GET `/v1/duplicate-content` [View API reference](https://domscan.net/docs/products/duplicate-content#getDuplicateContent) ## GET `/v1/duplicate-content` Operation: `getDuplicateContent` Credits and authentication: 5 Authentication required GET /v1/duplicate-content Credits: 5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | urls | string | required | #### Response fields | Field | Type | | --- | --- | | `status` | string | | `checked_at` | string | | `threshold` | number | | `pages[]` | object[] | | `pages[]` | object | | `pages[].url` | string | | `pages[].final_url` | string | | `pages[].status` | string | | `pages[].reason` | string \| null | | `pages[].http_status` | integer \| null | | `pages[].title` | string \| null | | `pages[].meta_description` | string \| null | | `pages[].h1` | string \| null | | `pages[].canonical` | string \| null | | `pages[].word_count` | integer | | `pages[].comparable` | boolean | | `pages[].comparison_reason` | string \| null | | `pairs[]` | object[] | | `pairs[]` | object | | `pairs[].a` | string | | `pairs[].b` | string | | `pairs[].similarity` | number \| null | | `pairs[].containment` | number \| null | | `pairs[].near_duplicate` | boolean \| null | | `pairs[].comparable` | boolean | | `pairs[].canonicalized` | boolean | | `pairs[].same_final_url` | boolean | | `pairs[].reason` | string \| null | | `clusters[]` | string[][] | | `clusters[][]` | string[] | | `duplicates` | object | | `duplicates.titles[]` | object[] | | `duplicates.titles[]` | object | | `duplicates.titles[].value` | string | | `duplicates.titles[].urls[]` | string[] | | `duplicates.meta_descriptions[]` | object[] | | `duplicates.meta_descriptions[]` | object | | `duplicates.meta_descriptions[].value` | string | | `duplicates.meta_descriptions[].urls[]` | string[] | | `duplicates.h1[]` | object[] | | `duplicates.h1[]` | object | | `duplicates.h1[].value` | string | | `duplicates.h1[].urls[]` | string[] | | `summary` | object | | `summary.pages` | integer | | `summary.readable` | integer | | `summary.unknown` | integer | | `summary.comparable_pairs` | integer | | `summary.unknown_pairs` | integer | | `summary.same_final_url_pairs` | integer | | `summary.near_duplicate_pairs` | integer | | `summary.uncanonicalized_near_duplicates` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/duplicate-content?urls=https%3A%2F%2Fexample.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/duplicate-content?urls=https%3A%2F%2Fexample.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/duplicate-content?urls=https%3A%2F%2Fexample.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/duplicate-content?urls=https%3A%2F%2Fexample.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/duplicate-content?urls=https%3A%2F%2Fexample.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "status": "ok", "checked_at": "2026-10-13T12:00:00.000Z", "threshold": 0.8, "pages": [ { "url": "https://example.com/a", "final_url": "https://example.com/a", "status": "ok", "reason": null, "http_status": 200, "title": "Trail shoes", "meta_description": "Shop trail shoes", "h1": "Trail shoes", "canonical": null, "word_count": 640, "comparable": true, "comparison_reason": null }, { "url": "https://example.com/b", "final_url": "https://example.com/b", "status": "ok", "reason": null, "http_status": 200, "title": "Trail shoes", "meta_description": "Shop trail shoes", "h1": "Trail running shoes", "canonical": null, "word_count": 655, "comparable": true, "comparison_reason": null } ], "pairs": [ { "a": "https://example.com/a", "b": "https://example.com/b", "similarity": 0.91, "containment": 0.96, "near_duplicate": true, "comparable": true, "canonicalized": false, "same_final_url": false, "reason": null } ], "clusters": [ [ "https://example.com/a", "https://example.com/b" ] ], "duplicates": { "titles": [ { "value": "trail shoes", "urls": [ "https://example.com/a", "https://example.com/b" ] } ], "meta_descriptions": [ { "value": "shop trail shoes", "urls": [ "https://example.com/a", "https://example.com/b" ] } ], "h1": [] }, "summary": { "pages": 2, "readable": 2, "unknown": 0, "comparable_pairs": 1, "unknown_pairs": 0, "same_final_url_pairs": 0, "near_duplicate_pairs": 1, "uncanonicalized_near_duplicates": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/site-audit # Site audit and SEO crawler API API Crawl up to 50 pages and find broken links, duplicates and on-page issues. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/site-audit-api) ## Operations GET `/v1/site-audit` [View API reference](https://domscan.net/docs/products/site-audit#getSiteAudit) ## GET `/v1/site-audit` Operation: `getSiteAudit` Credits and authentication: 10-35 Authentication required GET /v1/site-audit Credits: 10-35 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | max_pages | integer Allowed values `10`, `25`, `50` Default `10` | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `robots_txt` | string | | `max_pages` | integer | | `summary` | object | | `summary.pages_crawled` | integer | | `summary.pages_ok` | integer | | `summary.pages_not_found` | integer | | `summary.pages_unknown` | integer | | `summary.pages_not_html` | integer | | `summary.pages_redirect_only` | integer | | `summary.discovered_not_crawled` | integer | | `summary.blocked_by_robots` | integer | | `summary.near_duplicate_unknown_pairs` | integer | | `summary.average_score` | integer \| null | | `summary.crawl_complete` | boolean | | `summary.duration_ms` | integer | | `issues` | object | | `issues.broken_internal_links[]` | object[] | | `issues.broken_internal_links[]` | object | | `issues.broken_internal_links[].url` | string | | `issues.broken_internal_links[].http_status` | integer \| null | | `issues.broken_internal_links[].linked_from[]` | string[] | | `issues.internal_redirects[]` | object[] | | `issues.internal_redirects[]` | object | | `issues.internal_redirects[].url` | string | | `issues.internal_redirects[].final_url` | string | | `issues.internal_redirects[].linked_from[]` | string[] | | `issues.duplicate_titles[]` | object[] | | `issues.duplicate_titles[]` | object | | `issues.duplicate_titles[].value` | string | | `issues.duplicate_titles[].urls[]` | string[] | | `issues.duplicate_meta_descriptions[]` | object[] | | `issues.duplicate_meta_descriptions[]` | object | | `issues.duplicate_meta_descriptions[].value` | string | | `issues.duplicate_meta_descriptions[].urls[]` | string[] | | `issues.duplicate_h1[]` | object[] | | `issues.duplicate_h1[]` | object | | `issues.duplicate_h1[].value` | string | | `issues.duplicate_h1[].urls[]` | string[] | | `issues.near_duplicate_content[]` | object[] | | `issues.near_duplicate_content[]` | object | | `issues.near_duplicate_content[].a` | string | | `issues.near_duplicate_content[].b` | string | | `issues.near_duplicate_content[].similarity` | number | | `issues.noindex_pages[]` | string[] | | `issues.canonicalized_pages[]` | object[] | | `issues.canonicalized_pages[]` | object | | `issues.canonicalized_pages[].url` | string | | `issues.canonicalized_pages[].canonical` | string \| null | | `issues.thin_pages[]` | object[] | | `issues.thin_pages[]` | object | | `issues.thin_pages[].url` | string | | `issues.thin_pages[].word_count` | integer \| null | | `issues.onpage_checks[]` | object[] | | `issues.onpage_checks[]` | object | | `issues.onpage_checks[].check` | string | | `issues.onpage_checks[].pages` | integer | | `pages[]` | object[] | | `pages[]` | object | | `pages[].url` | string | | `pages[].final_url` | string | | `pages[].depth` | integer | | `pages[].status` | string | | `pages[].reason` | string \| null | | `pages[].http_status` | integer \| null | | `pages[].redirect_count` | integer | | `pages[].title` | string \| null | | `pages[].word_count` | integer \| null | | `pages[].score` | integer \| null | | `pages[].indexable` | boolean \| null | | `pages[].canonical` | string \| null | | `pages[].internal_links` | integer | | `pages[].inlinks` | integer | | `pages[].issues[]` | string[] | | `pages[].redirect_only` | boolean | | `caveats[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/site-audit?url=https%3A%2F%2Fexample.com&max_pages=10" ``` ```javascript const response = await fetch("https://domscan.net/v1/site-audit?url=https%3A%2F%2Fexample.com&max_pages=10", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/site-audit?url=https%3A%2F%2Fexample.com&max_pages=10", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/site-audit?url=https%3A%2F%2Fexample.com&max_pages=10", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/site-audit?url=https%3A%2F%2Fexample.com&max_pages=10") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "robots_txt": "rules", "max_pages": 10, "summary": { "pages_crawled": 10, "pages_ok": 9, "pages_not_found": 1, "pages_unknown": 0, "pages_not_html": 0, "pages_redirect_only": 0, "discovered_not_crawled": 34, "blocked_by_robots": 2, "near_duplicate_unknown_pairs": 3, "average_score": 88, "crawl_complete": false, "duration_ms": 14200 }, "issues": { "broken_internal_links": [ { "url": "https://example.com/old-sale", "http_status": 404, "linked_from": [ "https://example.com/" ] } ], "internal_redirects": [ { "url": "https://example.com/shoes", "final_url": "https://example.com/shoes/", "linked_from": [ "https://example.com/" ] } ], "duplicate_titles": [], "duplicate_meta_descriptions": [ { "value": "shop trail shoes", "urls": [ "https://example.com/a", "https://example.com/b" ] } ], "duplicate_h1": [], "near_duplicate_content": [ { "a": "https://example.com/a", "b": "https://example.com/b", "similarity": 0.91 } ], "noindex_pages": [], "canonicalized_pages": [], "thin_pages": [ { "url": "https://example.com/contact", "word_count": 74 } ], "onpage_checks": [ { "check": "images_alt", "pages": 6 } ] }, "pages": [ { "url": "https://example.com/", "final_url": "https://example.com/", "depth": 0, "status": "ok", "reason": null, "http_status": 200, "redirect_count": 0, "title": "Example Outdoor", "word_count": 820, "score": 91, "indexable": true, "canonical": "https://example.com/", "internal_links": 42, "inlinks": 0, "issues": [ "images_alt" ], "redirect_only": false } ], "caveats": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/screenshot # Website screenshot API API Capture any page as an image or PDF on desktop or mobile. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/screenshot-api) ## Operations GET `/v1/screenshot` [View API reference](https://domscan.net/docs/products/screenshot#getScreenshot) ## GET `/v1/screenshot` Operation: `getScreenshot` Credits and authentication: 10 Authentication required GET /v1/screenshot Credits: 10 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | device | string Allowed values `desktop`, `mobile` Default `desktop` | optional | | full_page | boolean | optional | | format | string Allowed values `png`, `jpeg`, `webp`, `pdf` Default `png` | optional | | output | string Allowed values `json`, `binary` Default `json` | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `http_status` | integer \| null | | `redirect_count` | integer | | `duration_ms` | integer | | `resource_limit_reached` | boolean | | `capture` | object | | `capture.format` | string | | `capture.mime_type` | string | | `capture.device` | string | | `capture.full_page` | boolean | | `capture.width` | integer \| null | | `capture.height` | integer \| null | | `capture.bytes` | integer | | `capture.format_fallback` | string \| null | | `capture.data_base64` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/screenshot?url=https%3A%2F%2Fexample.com&device=desktop&full_page=false&format=png&output=json" ``` ```javascript const response = await fetch("https://domscan.net/v1/screenshot?url=https%3A%2F%2Fexample.com&device=desktop&full_page=false&format=png&output=json", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/screenshot?url=https%3A%2F%2Fexample.com&device=desktop&full_page=false&format=png&output=json", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/screenshot?url=https%3A%2F%2Fexample.com&device=desktop&full_page=false&format=png&output=json", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/screenshot?url=https%3A%2F%2Fexample.com&device=desktop&full_page=false&format=png&output=json") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "final_url": "https://example.com/", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "http_status": 200, "redirect_count": 0, "duration_ms": 4210, "resource_limit_reached": false, "capture": { "format": "png", "mime_type": "image/png", "device": "desktop", "full_page": false, "width": 1366, "height": 768, "bytes": 182340, "data_base64": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/accessibility # Accessibility audit API API Run an automated WCAG audit with violations, affected elements and a score. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/accessibility-audit-api) ## Operations GET `/v1/accessibility` [View API reference](https://domscan.net/docs/products/accessibility#getAccessibilityAudit) ## GET `/v1/accessibility` Operation: `getAccessibilityAudit` Credits and authentication: 8 Authentication required GET /v1/accessibility Credits: 8 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | standard | string Allowed values `wcag2a`, `wcag2aa`, `wcag21aa`, `wcag22aa` | optional | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `http_status` | integer \| null | | `redirect_count` | integer | | `duration_ms` | integer | | `resource_limit_reached` | boolean | | `standard` | string \| null | | `score` | integer \| null | | `engine` | object | | `engine.name` | string | | `engine.version` | string \| null | | `summary` | object | | `summary.violations` | integer | | `summary.affected_elements` | integer | | `summary.by_impact` | object | | `summary.by_impact.critical` | integer | | `summary.by_impact.serious` | integer | | `summary.by_impact.moderate` | integer | | `summary.by_impact.minor` | integer | | `summary.passes` | integer | | `summary.incomplete` | integer | | `summary.inapplicable` | integer | | `violations[]` | object[] | | `violations[]` | object | | `violations[].id` | string | | `violations[].impact` | string | | `violations[].help` | string | | `violations[].help_url` | string \| null | | `violations[].wcag_level` | string \| null | | `violations[].tags[]` | string[] | | `violations[].node_count` | integer | | `violations[].nodes[]` | object[] | | `violations[].nodes[]` | object | | `violations[].nodes[].target` | string | | `violations[].nodes[].html` | string | | `violations[].nodes[].failure_summary` | string | | `violations_truncated` | boolean | | `incomplete[]` | object[] | | `incomplete[]` | object | | `incomplete[].id` | string | | `incomplete[].impact` | string \| null | | `incomplete[].help` | string | | `incomplete[].node_count` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/accessibility?url=https%3A%2F%2Fexample.com&standard=wcag2a" ``` ```javascript const response = await fetch("https://domscan.net/v1/accessibility?url=https%3A%2F%2Fexample.com&standard=wcag2a", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/accessibility?url=https%3A%2F%2Fexample.com&standard=wcag2a", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/accessibility?url=https%3A%2F%2Fexample.com&standard=wcag2a", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/accessibility?url=https%3A%2F%2Fexample.com&standard=wcag2a") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "final_url": "https://example.com/", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "http_status": 200, "redirect_count": 0, "duration_ms": 4210, "resource_limit_reached": false, "score": 84, "engine": { "name": "axe-core", "version": "4.10.3" }, "summary": { "violations": 2, "affected_elements": 8, "by_impact": { "critical": 1, "serious": 1, "moderate": 0, "minor": 0 }, "passes": 38, "incomplete": 1, "inapplicable": 41 }, "violations": [ { "id": "image-alt", "impact": "critical", "help": "Images must have alternative text", "help_url": "https://dequeuniversity.com/rules/axe/4.10/image-alt", "wcag_level": "A", "tags": [ "wcag2a", "wcag111" ], "node_count": 2, "nodes": [ { "target": "main > img.hero", "html": "", "failure_summary": "Element does not have an alt attribute" } ] } ], "incomplete": [ { "id": "color-contrast", "impact": "serious", "help": "Elements must meet minimum color contrast ratio thresholds", "node_count": 3 } ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/cookie-scan # Cookie and tracker scanner API API List cookies, trackers and consent manager seen before consent. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/cookie-scanner-api) ## Operations GET `/v1/cookie-scan` [View API reference](https://domscan.net/docs/products/cookie-scan#getCookieScan) ## GET `/v1/cookie-scan` Operation: `getCookieScan` Credits and authentication: 8 Authentication required GET /v1/cookie-scan Credits: 8 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `http_status` | integer \| null | | `redirect_count` | integer | | `duration_ms` | integer | | `resource_limit_reached` | boolean | | `summary` | object | | `summary.cookies` | integer | | `summary.first_party_cookies` | integer | | `summary.third_party_cookies` | integer | | `summary.session_cookies` | integer | | `summary.persistent_cookies` | integer | | `summary.trackers` | integer | | `summary.third_party_domains` | integer | | `consent` | object | | `consent.cmp` | string \| null | | `consent.tcf_api` | boolean | | `cookies[]` | object[] | | `cookies[]` | object | | `cookies[].name` | string | | `cookies[].domain` | string | | `cookies[].path` | string | | `cookies[].party` | string | | `cookies[].session` | boolean | | `cookies[].lifetime_days` | integer \| null | | `cookies[].secure` | boolean | | `cookies[].http_only` | boolean | | `cookies[].same_site` | string \| null | | `cookies[].size` | integer | | `cookies[].tracker` | object | | `cookies[].tracker.name` | string | | `cookies[].tracker.category` | string | | `trackers[]` | object[] | | `trackers[]` | object | | `trackers[].name` | string | | `trackers[].category` | string | | `trackers[].requests` | integer | | `trackers[].cookies` | integer | | `third_party_domains[]` | object[] | | `third_party_domains[]` | object | | `third_party_domains[].domain` | string | | `third_party_domains[].requests` | integer | | `storage` | object | | `storage.local_storage_keys` | integer | | `storage.session_storage_keys` | integer | | `findings[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/cookie-scan?url=https%3A%2F%2Fexample.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/cookie-scan?url=https%3A%2F%2Fexample.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/cookie-scan?url=https%3A%2F%2Fexample.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/cookie-scan?url=https%3A%2F%2Fexample.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/cookie-scan?url=https%3A%2F%2Fexample.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "final_url": "https://example.com/", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "http_status": 200, "redirect_count": 0, "duration_ms": 4210, "resource_limit_reached": false, "summary": { "cookies": 2, "first_party_cookies": 1, "third_party_cookies": 1, "session_cookies": 1, "persistent_cookies": 1, "trackers": 1, "third_party_domains": 3 }, "consent": { "cmp": "onetrust", "tcf_api": true }, "cookies": [ { "name": "_ga", "domain": ".example.com", "path": "/", "party": "first", "session": false, "lifetime_days": 400, "secure": false, "http_only": false, "same_site": "Lax", "size": 30, "tracker": null }, { "name": "IDE", "domain": ".doubleclick.net", "path": "/", "party": "third", "session": true, "lifetime_days": null, "secure": true, "http_only": true, "same_site": "None", "size": 60, "tracker": { "name": "Google Ads", "category": "advertising" } } ], "trackers": [ { "name": "Google Analytics", "category": "analytics", "requests": 3 } ], "third_party_domains": [ { "domain": "google-analytics.com", "requests": 3 } ], "storage": { "local_storage_keys": 4, "session_storage_keys": 1 }, "findings": [ "trackers_load_before_consent", "third_party_cookies", "cookie_lifetime_over_13_months", "cookies_without_secure_flag" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/page-weight # Page weight and resource API API Measure page bytes, requests, third parties and load timings. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/page-weight-api) ## Operations GET `/v1/page-weight` [View API reference](https://domscan.net/docs/products/page-weight#getPageWeight) ## GET `/v1/page-weight` Operation: `getPageWeight` Credits and authentication: 6 Authentication required GET /v1/page-weight Credits: 6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | #### Response fields | Field | Type | | --- | --- | | `url` | string | | `final_url` | string | | `status` | string | | `reason` | string \| null | | `checked_at` | string | | `http_status` | integer \| null | | `redirect_count` | integer | | `duration_ms` | integer | | `resource_limit_reached` | boolean | | `summary` | object | | `summary.requests` | integer | | `summary.blocked_requests` | integer | | `summary.total_bytes` | integer | | `summary.third_party_requests` | integer | | `summary.third_party_bytes` | integer | | `summary.transfer_bytes` | integer | | `by_type[]` | object[] | | `by_type[]` | object | | `by_type[].type` | string | | `by_type[].requests` | integer | | `by_type[].bytes` | integer | | `largest[]` | object[] | | `largest[]` | object | | `largest[].url` | string | | `largest[].type` | string | | `largest[].bytes` | integer | | `largest[].mime_type` | string \| null | | `third_parties[]` | object[] | | `third_parties[]` | object | | `third_parties[].domain` | string | | `third_parties[].requests` | integer | | `third_parties[].bytes` | integer | | `render_blocking[]` | object[] | | `render_blocking[]` | object | | `render_blocking[].url` | string | | `render_blocking[].type` | string | | `timing` | object | | `timing.ttfb_ms` | number \| null | | `timing.first_contentful_paint_ms` | number \| null | | `timing.dom_content_loaded_ms` | number \| null | | `timing.load_ms` | number \| null | | `findings[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/page-weight?url=https%3A%2F%2Fexample.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/page-weight?url=https%3A%2F%2Fexample.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/page-weight?url=https%3A%2F%2Fexample.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/page-weight?url=https%3A%2F%2Fexample.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/page-weight?url=https%3A%2F%2Fexample.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "final_url": "https://example.com/", "status": "ok", "reason": null, "checked_at": "2026-10-13T12:00:00.000Z", "http_status": 200, "redirect_count": 0, "duration_ms": 4210, "resource_limit_reached": false, "summary": { "requests": 86, "blocked_requests": 4, "total_bytes": 3412887, "third_party_requests": 22, "third_party_bytes": 1210554, "transfer_bytes": 3425100 }, "by_type": [ { "type": "image", "requests": 31, "bytes": 1840221 }, { "type": "script", "requests": 28, "bytes": 1120334 } ], "largest": [ { "url": "https://example.com/hero.jpg", "type": "image", "bytes": 612004, "mime_type": "image/jpeg" } ], "third_parties": [ { "domain": "googletagmanager.com", "requests": 3, "bytes": 310442 } ], "render_blocking": [ { "url": "https://example.com/styles.css", "type": "stylesheet" } ], "timing": { "ttfb_ms": 180, "first_contentful_paint_ms": 1240, "dom_content_loaded_ms": 1610, "load_ms": 3890 }, "findings": [ "page_weight_over_3mb", "images_over_200kb", "render_blocking_resources" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/website-categorization # Website Categorization API Categorize a website by industry, content type, and topics. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/website-categorization-api) ## Operations GET `/v1/categorize` [View API reference](https://domscan.net/docs/products/website-categorization#categorizeWebsite) GET `/v1/categorize/taxonomy` [View API reference](https://domscan.net/docs/products/website-categorization#getCategorizationTaxonomy) POST `/v1/categorize/bulk` [View API reference](https://domscan.net/docs/products/website-categorization#categorizeWebsiteBulk) ## GET `/v1/categorize` Operation: `categorizeWebsite` Credits and authentication: 3 Authentication required GET /v1/categorize Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | | skip_cache | string Allowed values `0`, `1` | optional | | min_confidence | integer Default `0` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `url` | string | | `primary_category` | string \| null | | `primary_category_id` | string \| null | | `categories[]` | object[] | | `categories[]` | object | | `categories[].category_id` | string | | `categories[].category` | string | | `categories[].subcategory_id` | string \| null | | `categories[].subcategory` | string \| null | | `categories[].confidence` | integer | | `categories[].keywords_found[]` | string[] | | `categories[].signals[]` | object[] | | `categories[].signals[]` | object | | `categories[].signals[].source` | string | | `categories[].signals[].evidence` | string | | `primary_category_confidence` | string | | `title` | string \| null | | `description` | string \| null | | `language` | string \| null | | `language_confidence` | string | | `adult_content` | boolean | | `signals_used` | integer | | `cached` | boolean | | `total_time_ms` | integer | | `checked_at` | string | | `evidence_summary` | object | | `evidence_summary.analysis_status` | string | | `evidence_summary.content_observed` | boolean | | `evidence_summary.content_source` | string | | `evidence_summary.cache_status` | string | | `evidence_summary.stale` | boolean | | `evidence_summary.fetch_transport` | string \| null | | `evidence_summary.response_status` | integer \| null | | `evidence_summary.final_url` | string | | `evidence_summary.redirect_count` | integer | | `evidence_summary.body_truncated` | boolean | | `evidence_summary.unavailable_reason` | string | | `meta` | object | | `meta.served_by` | string | | `meta.cache_status` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/categorize?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=0&min_confidence=0" ``` ```javascript const response = await fetch("https://domscan.net/v1/categorize?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=0&min_confidence=0", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/categorize?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=0&min_confidence=0", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/categorize?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=0&min_confidence=0", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/categorize?url=https%3A%2F%2Fexample.com&domain=example.com&skip_cache=0&min_confidence=0") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "url": "https://example.com", "primary_category": "SaaS & Cloud", "primary_category_id": "IAB25", "categories": [ { "category_id": "IAB25", "category": "SaaS & Cloud", "subcategory_id": null, "subcategory": null, "confidence": 84, "keywords_found": [ "platform", "dashboard", "enterprise" ], "signals": [ { "source": "keyword_title", "evidence": "Matched platform and dashboard in the page title." } ] }, { "category_id": "IAB19", "category": "Technology & Computing", "subcategory_id": null, "subcategory": null, "confidence": 72, "keywords_found": [ "api", "developer", "automation" ], "signals": [ { "source": "keyword_body", "evidence": "Developer-focused terms appear repeatedly in page copy." } ] } ], "primary_category_confidence": "high", "title": "Developer platform for AI apps", "description": "Build with APIs, models, and cloud workflows", "language": "en", "language_confidence": "high", "adult_content": false, "signals_used": 12, "cached": false, "total_time_ms": 412, "checked_at": "2026-04-18T21:00:00Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/categorize/taxonomy` Operation: `getCategorizationTaxonomy` Credits and authentication: Free Authentication optional GET /v1/categorize/taxonomy Credits: 0 #### Response fields | Field | Type | | --- | --- | | `taxonomy` | string | | `version` | string | | `official_iab_taxonomy` | boolean | | `inspired_by` | string | | `category_count` | integer | | `subcategory_count` | integer | | `notes[]` | string[] | | `categories[]` | object[] | | `categories[]` | object | | `categories[].category_id` | string | | `categories[].category` | string | | `categories[].taxonomy_name` | string | | `categories[].ranked_category` | boolean | | `categories[].subcategories[]` | object[] | | `categories[].subcategories[]` | object | | `categories[].subcategories[].subcategory_id` | string | | `categories[].subcategories[].subcategory` | string | | `meta` | object | #### Example request ```bash curl "https://domscan.net/v1/categorize/taxonomy" ``` ```javascript const response = await fetch("https://domscan.net/v1/categorize/taxonomy"); const data = await response.json(); console.log(data); ``` ```python import requests response = requests.get( "https://domscan.net/v1/categorize/taxonomy", ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/categorize/taxonomy", nil) if err != nil { panic(err) } ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/categorize/taxonomy") request = Net::HTTP::Get.new(uri) #### Example response ```json { "taxonomy": "domscan-iab-inspired", "version": "v1", "official_iab_taxonomy": false, "inspired_by": "IAB Tech Lab Content Taxonomy 3.x", "category_count": 35, "subcategory_count": 134, "notes": [ "DomScan returns IAB-style IDs from its own IAB-inspired taxonomy.", "The category field matches the value returned by /v1/categorize for backward compatibility.", "IAB29 Adult is primarily exposed through the adult_content boolean in categorization responses." ], "categories": [ { "category_id": "IAB22", "category": "E-commerce", "taxonomy_name": "Shopping & E-commerce", "ranked_category": true, "subcategories": [ { "subcategory_id": "IAB22-1", "subcategory": "Online Retail" }, { "subcategory_id": "IAB22-2", "subcategory": "Deals & Coupons" } ] }, { "category_id": "IAB25", "category": "SaaS & Cloud", "taxonomy_name": "SaaS & Cloud", "ranked_category": true, "subcategories": [ { "subcategory_id": "IAB25-3", "subcategory": "Developer Tools" } ] } ] } ``` #### HTTP status codes - `200` OK - `429` Too Many Requests ## POST `/v1/categorize/bulk` Operation: `categorizeWebsiteBulk` Credits and authentication: 3 Authentication required POST /v1/categorize/bulk Credits: 3/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | urls | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.cached` | integer | | `meta.stale` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/categorize/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "urls": [ "https://example.com", "https://example.org" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/categorize/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "urls": [ "https://example.com", "https://example.org" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/categorize/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "urls": [ "https://example.com", "https://example.org", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "urls": [ "https://example.com", "https://example.org" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/categorize/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/categorize/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "urls" => [ "https://example.com", "https://example.org" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [], "meta": { "total": 1, "succeeded": 1, "failed": 1, "cached": 1, "stale": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/url-intelligence # Unified URL Intelligence API Extract normalized page metadata, preview fields, structured data, and public identity signals from a URL. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/url-metadata-api) ## Operations GET `/v1/url-intelligence` [View API reference](https://domscan.net/docs/products/url-intelligence#getUrlIntelligence) POST `/v1/url-intelligence/bulk` [View API reference](https://domscan.net/docs/products/url-intelligence#bulkGetUrlIntelligence) ## GET `/v1/url-intelligence` Operation: `getUrlIntelligence` Credits and authentication: 2 Authentication required GET /v1/url-intelligence Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | skip_cache | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `requested_url` | string | | `final_url` | string | | `status` | integer | | `fetch_state` | string | | `content_type` | string \| null | | `redirects` | integer | | `title` | string \| null | | `description` | string \| null | | `canonical_url` | string \| null | | `language` | string \| null | | `favicon_url` | string \| null | | `preview_image_url` | string \| null | | `manifest_url` | string \| null | | `theme_color` | string \| null | | `open_graph` | object | | `twitter_card` | object | | `structured_data` | object | | `structured_data.types[]` | string[] | | `structured_data.items` | integer | | `structured_data.parse_errors` | integer | | `robots` | object | | `robots.meta[]` | string[] | | `robots.header[]` | string[] | | `robots.indexable` | boolean \| null | | `security_headers` | object | | `links` | object | | `links.total` | integer | | `links.internal` | integer | | `links.external` | integer | | `social_profiles[]` | object[] | | `social_profiles[]` | object | | `social_profiles[].platform` | string | | `social_profiles[].type` | string | | `social_profiles[].handle` | string \| null | | `social_profiles[].url` | string | | `social_profiles[].source` | string | | `social_profiles[].confidence` | string | | `contacts` | object | | `contacts.emails[]` | string[] | | `contacts.phones[]` | string[] | | `meta` | object | | `meta.checked_at` | string | | `meta.cached` | boolean | | `meta.fetch_transport` | string | | `meta.fetch_error` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/url-intelligence?url=https%3A%2F%2Fexample.com&skip_cache=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/url-intelligence?url=https%3A%2F%2Fexample.com&skip_cache=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/url-intelligence?url=https%3A%2F%2Fexample.com&skip_cache=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/url-intelligence?url=https%3A%2F%2Fexample.com&skip_cache=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/url-intelligence?url=https%3A%2F%2Fexample.com&skip_cache=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "requested_url": "https://www.example.com/", "final_url": "https://www.example.com/", "status": 200, "fetch_state": "ok", "content_type": "text/html; charset=UTF-8", "redirects": 0, "title": "Example Co | Simple tools for small teams", "description": "Example Co builds simple tools for small teams.", "canonical_url": "https://www.example.com/", "language": "en", "favicon_url": "https://www.example.com/favicon.ico", "preview_image_url": "https://www.example.com/og.png", "manifest_url": "https://www.example.com/site.webmanifest", "theme_color": "#0b5fff", "open_graph": { "title": "Example Co", "type": "website", "url": "https://www.example.com/", "image": "https://www.example.com/og.png" }, "twitter_card": { "card": "summary_large_image", "title": "Example Co" }, "structured_data": { "types": [ "Organization" ], "items": 1, "parse_errors": 0 }, "robots": { "meta": [ "index", "follow" ], "header": [], "indexable": true }, "security_headers": { "content-security-policy": "default-src 'self'", "strict-transport-security": "max-age=63072000; includeSubDomains", "x-content-type-options": "nosniff", "x-frame-options": "SAMEORIGIN", "referrer-policy": "strict-origin-when-cross-origin", "permissions-policy": null, "cross-origin-opener-policy": null }, "links": { "total": 3, "internal": 2, "external": 1 }, "social_profiles": [ { "platform": "linkedin", "type": "social", "handle": "example-co", "url": "https://www.linkedin.com/company/example-co", "source": "same_as", "confidence": "high" }, { "platform": "github", "type": "developer", "handle": "example-co", "url": "https://github.com/example-co", "source": "same_as", "confidence": "high" } ], "contacts": { "emails": [ "hello@example.com" ], "phones": [] }, "meta": { "checked_at": "2026-10-09T10:15:30.000Z", "cached": false, "fetch_transport": "edge_relay" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## POST `/v1/url-intelligence/bulk` Operation: `bulkGetUrlIntelligence` Credits and authentication: 2 Authentication required POST /v1/url-intelligence/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | urls | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `results[].input` | string | | `results[].data` | object | | `results[].error` | object | | `results[].error.error` | object | | `results[].error.error.code` | string | | `results[].error.error.type` | string | | `results[].error.error.message` | string | | `results[].error.error.status` | integer | | `results[].error.error.retryable` | boolean | | `results[].error.error.request_id` | string | | `results[].error.error.suggestion` | string | | `results[].error.error.details` | object | | `results[].error.error.retry_after` | integer | | `results[].error.error.docs_url` | string | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.unknown` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/url-intelligence/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "urls": [ "https://example.com", "https://github.com/about" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/url-intelligence/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "urls": [ "https://example.com", "https://github.com/about" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/url-intelligence/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "urls": [ "https://example.com", "https://github.com/about", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "urls": [ "https://example.com", "https://github.com/about" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/url-intelligence/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/url-intelligence/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "urls" => [ "https://example.com", "https://github.com/about" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "input": "example", "data": {}, "error": { "error": { "code": "INVALID_DOMAIN", "type": "authentication_error", "message": "Invalid domain format", "status": 400, "retryable": false, "request_id": "request-id", "docs_url": "https://domscan.net/docs/check-availability", "suggestion": "example", "details": {}, "retry_after": 300 } } } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "unknown": 1, "max_items": 10, "credits_per_item": 2, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/name-availability # Name Availability API API Check a name across domains, social handles and package registries at once. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/name-availability-api) ## Operations GET `/v1/name-check` [View API reference](https://domscan.net/docs/products/name-availability#checkNameAvailability) ## GET `/v1/name-check` Operation: `checkNameAvailability` Credits and authentication: 5 Authentication required GET /v1/name-check Credits: 5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | name | string | required | | tlds | string | optional | | platforms | string | optional | | packages | string | optional | #### Response fields | Field | Type | | --- | --- | | `name` | string | | `status` | string | | `checked_at` | string | | `verdict` | string | | `score` | integer \| null | | `determinacy` | integer | | `summary` | object | | `summary.com_available` | boolean \| null | | `summary.domains` | object | | `summary.domains.checked` | integer | | `summary.domains.free` | integer | | `summary.domains.taken` | integer | | `summary.domains.unknown` | integer | | `summary.handles` | object | | `summary.handles.checked` | integer | | `summary.handles.free` | integer | | `summary.handles.taken` | integer | | `summary.handles.unknown` | integer | | `summary.packages` | object | | `summary.packages.checked` | integer | | `summary.packages.free` | integer | | `summary.packages.taken` | integer | | `summary.packages.unknown` | integer | | `domains[]` | object[] | | `domains[]` | object | | `domains[].domain` | string | | `domains[].tld` | string | | `domains[].status` | string | | `domains[].reason` | string \| null | | `handles[]` | object[] | | `handles[]` | object | | `handles[].platform` | string | | `handles[].status` | string | | `handles[].url` | string \| null | | `handles[].reason` | string \| null | | `packages[]` | object[] | | `packages[]` | object | | `packages[].registry` | string | | `packages[].name` | string | | `packages[].status` | string | | `packages[].url` | string \| null | | `packages[].reason` | string \| null | | `meta` | object | | `meta.duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/name-check?name=acmeflow&tlds=com%2Cio%2Cai&platforms=github%2Cinstagram%2Ctiktok&packages=npm%2Cpypi" ``` ```javascript const response = await fetch("https://domscan.net/v1/name-check?name=acmeflow&tlds=com%2Cio%2Cai&platforms=github%2Cinstagram%2Ctiktok&packages=npm%2Cpypi", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/name-check?name=acmeflow&tlds=com%2Cio%2Cai&platforms=github%2Cinstagram%2Ctiktok&packages=npm%2Cpypi", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/name-check?name=acmeflow&tlds=com%2Cio%2Cai&platforms=github%2Cinstagram%2Ctiktok&packages=npm%2Cpypi", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/name-check?name=acmeflow&tlds=com%2Cio%2Cai&platforms=github%2Cinstagram%2Ctiktok&packages=npm%2Cpypi") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "name": "acmeflow", "status": "ok", "checked_at": "2026-10-13T18:00:00.000Z", "verdict": "mostly_available", "score": 80, "determinacy": 100, "summary": { "com_available": false, "domains": { "checked": 2, "free": 1, "taken": 1, "unknown": 0 }, "handles": { "checked": 2, "free": 2, "taken": 0, "unknown": 0 }, "packages": { "checked": 1, "free": 1, "taken": 0, "unknown": 0 } }, "domains": [ { "domain": "acmeflow.com", "tld": "com", "status": "taken", "reason": null }, { "domain": "acmeflow.io", "tld": "io", "status": "available", "reason": null } ], "handles": [ { "platform": "github", "status": "available", "url": null, "reason": null }, { "platform": "instagram", "status": "available", "url": null, "reason": null } ], "packages": [ { "registry": "npm", "name": "acmeflow", "status": "not_found", "url": null, "reason": "similar_name_rules" } ], "meta": { "duration_ms": 4210 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-availability # Check Domain Availability API Check if a domain name is available across one or more TLDs. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/check-domain-availability) ## Operations GET `/v1/status` [View API reference](https://domscan.net/docs/products/domain-availability#checkDomainAvailability) POST `/v1/status/bulk` [View API reference](https://domscan.net/docs/products/domain-availability#bulkCheckDomains) ## GET `/v1/status` Operation: `checkDomainAvailability` Credits and authentication: 1 Authentication required GET /v1/status Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | name | string | optional | | tlds | string | optional | | domain | string | optional | | prefer_cache | boolean Default `false` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `name` | string | | `results[]` | object[] | | `results[]` | object | | `results[].classification` | object | | `results[].classification.status` | string | | `results[].classification.reason` | string | | `results[].classification.evidence` | object | | `results[].classification.evidence.source` | string | | `results[].classification.evidence.method` | string | | `results[].classification.evidence.observed_at` | string | | `results[].classification.evidence.detail` | string | | `results[].classification.checked_at` | string | | `results[].domain` | string | | `results[].tld` | string | | `results[].available` | boolean \| null | | `results[].availability_reason` | string | | `results[].source` | string | | `results[].confidence` | string | | `results[].checked_at` | string | | `results[].latency_ms` | integer | | `results[].cache_age_s` | integer | | `results[].registry_status[]` | string[] | | `results[].rdap_events[]` | object[] | | `results[].rdap_events[]` | object | | `results[].rdap_events[].eventAction` | string | | `results[].rdap_events[].eventDate` | string | | `results[].proof` | object | | `results[].dns_status` | object | | `results[].dns_status.has_nameservers` | boolean | | `results[].dns_status.resolvable` | boolean | | `results[].dns_status.checked` | boolean | | `results[].timing` | object | | `results[].timing.cache_lookup_ms` | integer | | `results[].timing.rdap_query_ms` | integer | | `results[].timing.dns_check_ms` | integer | | `results[].timing.total_ms` | integer | | `results[].status_flags[]` | string[] | | `results[].status` | string | | `results[].lifecycle_phase` | string | | `results[].is_public_suffix` | boolean | | `results[].error` | object | | `results[].error.code` | string | | `results[].error.message` | string | | `results[].error.suggestion` | string | | `results[].error.cause` | string | | `scope` | string | | `confidence_summary` | object | | `confidence_summary.scope` | string | | `confidence_summary.requested_count` | integer | | `confidence_summary.result_count` | integer | | `confidence_summary.invalid_count` | integer | | `confidence_summary.available_count` | integer | | `confidence_summary.registered_count` | integer | | `confidence_summary.restricted_count` | integer | | `confidence_summary.authoritative_count` | integer | | `confidence_summary.heuristic_count` | integer | | `confidence_summary.cached_count` | integer | | `confidence_summary.error_count` | integer | | `confidence_summary.ambiguous_count` | integer | | `confidence_summary.source_counts` | object | | `confidence_summary.primary_source` | string \| null | | `confidence_summary.cache_status` | string | | `confidence_summary.rdap_calls` | integer | | `confidence_summary.refreshes` | integer | | `confidence_summary.cache_preference_misses` | integer | | `confidence_summary.fallback_chain[]` | string[] | | `confidence_summary.confidence_level` | string | | `confidence_summary.determinacy_rate` | number | | `confidence_summary.ambiguity_reason` | string \| null | | `meta` | object | | `meta.total_checked` | integer | | `meta.available_count` | integer | | `meta.duration_ms` | integer | | `meta.served_by` | string | | `meta.scope_description` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/status?name=mycompany&tlds=com%2Cnet%2Corg%2Cio&domain=mycompany.com&prefer_cache=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/status?name=mycompany&tlds=com%2Cnet%2Corg%2Cio&domain=mycompany.com&prefer_cache=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/status?name=mycompany&tlds=com%2Cnet%2Corg%2Cio&domain=mycompany.com&prefer_cache=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/status?name=mycompany&tlds=com%2Cnet%2Corg%2Cio&domain=mycompany.com&prefer_cache=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/status?name=mycompany&tlds=com%2Cnet%2Corg%2Cio&domain=mycompany.com&prefer_cache=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "name": "mycompany", "results": [ { "domain": "mycompany.com", "tld": "com", "available": false, "source": "rdap", "latency_ms": 45 }, { "domain": "mycompany.io", "tld": "io", "available": true, "source": "rdap", "latency_ms": 67 } ], "meta": { "total_checked": 2, "available_count": 1, "duration_ms": 120 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/status/bulk` Operation: `bulkCheckDomains` Credits and authentication: 1 Authentication required POST /v1/status/bulk Credits: 1/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | | options | object | optional | | prefer_cache | boolean Default `false` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `results[]` | object[] | | `results[]` | object | | `results[].classification` | object | | `results[].classification.status` | string | | `results[].classification.reason` | string | | `results[].classification.evidence` | object | | `results[].classification.evidence.source` | string | | `results[].classification.evidence.method` | string | | `results[].classification.evidence.observed_at` | string | | `results[].classification.evidence.detail` | string | | `results[].classification.checked_at` | string | | `results[].domain` | string | | `results[].tld` | string | | `results[].available` | boolean \| null | | `results[].availability_reason` | string | | `results[].source` | string | | `results[].confidence` | string | | `results[].checked_at` | string | | `results[].latency_ms` | integer | | `results[].cache_age_s` | integer | | `results[].registry_status[]` | string[] | | `results[].rdap_events[]` | object[] | | `results[].rdap_events[]` | object | | `results[].rdap_events[].eventAction` | string | | `results[].rdap_events[].eventDate` | string | | `results[].proof` | object | | `results[].dns_status` | object | | `results[].dns_status.has_nameservers` | boolean | | `results[].dns_status.resolvable` | boolean | | `results[].dns_status.checked` | boolean | | `results[].timing` | object | | `results[].timing.cache_lookup_ms` | integer | | `results[].timing.rdap_query_ms` | integer | | `results[].timing.dns_check_ms` | integer | | `results[].timing.total_ms` | integer | | `results[].status_flags[]` | string[] | | `results[].status` | string | | `results[].lifecycle_phase` | string | | `results[].is_public_suffix` | boolean | | `results[].error` | object | | `results[].error.code` | string | | `results[].error.message` | string | | `results[].error.suggestion` | string | | `results[].error.cause` | string | | `confidence_summary` | object | | `confidence_summary.scope` | string | | `confidence_summary.requested_count` | integer | | `confidence_summary.result_count` | integer | | `confidence_summary.invalid_count` | integer | | `confidence_summary.available_count` | integer | | `confidence_summary.registered_count` | integer | | `confidence_summary.restricted_count` | integer | | `confidence_summary.authoritative_count` | integer | | `confidence_summary.heuristic_count` | integer | | `confidence_summary.cached_count` | integer | | `confidence_summary.error_count` | integer | | `confidence_summary.ambiguous_count` | integer | | `confidence_summary.source_counts` | object | | `confidence_summary.primary_source` | string \| null | | `confidence_summary.cache_status` | string | | `confidence_summary.rdap_calls` | integer | | `confidence_summary.refreshes` | integer | | `confidence_summary.cache_preference_misses` | integer | | `confidence_summary.fallback_chain[]` | string[] | | `confidence_summary.confidence_level` | string | | `confidence_summary.determinacy_rate` | number | | `confidence_summary.ambiguity_reason` | string \| null | | `meta` | object | | `meta.total_checked` | integer | | `meta.available_count` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/status/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "startup.io", "brand.ai" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/status/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "startup.io", "brand.ai" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/status/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "startup.io", "brand.ai", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "startup.io", "brand.ai" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/status/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/status/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "startup.io", "brand.ai" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "domain": "example.com", "tld": "com", "available": false, "source": "rdap", "latency_ms": 45 }, { "domain": "startup.io", "tld": "io", "available": true, "source": "rdap", "latency_ms": 67 }, { "domain": "brand.ai", "tld": "ai", "available": true, "source": "cache", "latency_ms": 2 } ], "meta": { "total_checked": 3, "available_count": 2, "duration_ms": 120 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-discovery # Domain Finder Recipe API Queue many supported API requests and collect their results without keeping a client connection open. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-discovery-api) ## Operations POST `/v1/domain-discovery/jobs` [View API reference](https://domscan.net/docs/products/domain-discovery#createDomainDiscoveryJob) ## POST `/v1/domain-discovery/jobs` Operation: `createDomainDiscoveryJob` Credits and authentication: 1 Authentication required POST /v1/domain-discovery/jobs Credits: 1/item #### Body parameters | Parameter | Type | required | | --- | --- | --- | | notify_webhook | unknown | optional | | tlds | string[] | required | | limit | integer | optional | | cursor | string | optional | | min_length | integer Default `3` | optional | | max_length | integer Default `16` | optional | | singular_only | boolean Default `false` | optional | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.webhook` | object | | `job.webhook.configured` | boolean | | `job.webhook.status` | string | | `job.webhook.attempts` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.results_csv_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | | `discovery` | object | | `discovery.corpus` | string | | `discovery.corpus_version` | string | | `discovery.total_matching_words` | integer | | `discovery.page_offset` | integer | | `discovery.page_words` | integer | | `discovery.domain_checks` | integer | | `discovery.tlds[]` | string[] | | `discovery.filters` | object | | `discovery.filters.min_length` | integer | | `discovery.filters.max_length` | integer | | `discovery.filters.singular_only` | boolean | | `discovery.credits_per_domain` | integer | | `discovery.next_cursor` | string \| null | #### Example request ```bash curl -X POST "https://domscan.net/v1/domain-discovery/jobs" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "tlds": [ "io", "ai" ], "limit": 50, "min_length": 4, "max_length": 8, "singular_only": true }' ``` ```javascript const response = await fetch("https://domscan.net/v1/domain-discovery/jobs", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "tlds": [ "io", "ai" ], "limit": 50, "min_length": 4, "max_length": 8, "singular_only": true }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/domain-discovery/jobs", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "tlds": [ "io", "ai", ], "limit": 50, "min_length": 4, "max_length": 8, "singular_only": True, }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "tlds": [ "io", "ai" ], "limit": 50, "min_length": 4, "max_length": 8, "singular_only": true }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/domain-discovery/jobs", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/domain-discovery/jobs") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "tlds" => [ "io", "ai" ], "limit" => 50, "min_length" => 4, "max_length" => 8, "singular_only" => true }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "job": { "id": "example-id", "status": "queued", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "webhook": { "configured": false, "status": "not_configured", "attempts": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "results_csv_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" }, "discovery": { "corpus": "iannuttall/unclaimed", "corpus_version": "example", "total_matching_words": 1, "page_offset": 1, "page_words": 1, "domain_checks": 1, "tlds": [ "com", "net", "org" ], "filters": { "min_length": 1, "max_length": 1, "singular_only": false }, "credits_per_domain": 1, "next_cursor": "example" } } ``` #### HTTP status codes - `200` OK - `202` Accepted - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/rdap-coverage # TLD Coverage API Lists TLDs with RDAP mappings and representative endpoint health. This is not a complete list of TLDs that can be checked; some lookups use traditional WHOIS fallback. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/rdap-coverage-api) ## Operations GET `/v1/coverage` [View API reference](https://domscan.net/docs/products/rdap-coverage#getCoverage) ## GET `/v1/coverage` Operation: `getCoverage` Credits and authentication: Free Authentication optional GET /v1/coverage Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | live | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `gtlds[]` | string[] | | `cctlds[]` | string[] | | `total_tlds` | integer | | `all_tlds[]` | string[] | | `rdap_health[]` | object[] | | `rdap_health[]` | object | | `rdap_health[].tld` | string | | `rdap_health[].endpoint` | string | | `rdap_health[].measurement_status` | string | | `rdap_health[].ok` | boolean \| null | | `rdap_health[].p50_ms` | number \| null | | `rdap_health[].error_rate` | number \| null | | `bootstrap_source` | string | | `bootstrap_last_updated` | string | | `meta` | object | | `meta.served_by` | string | | `meta.bootstrap_ttl_s` | integer | | `meta.live` | boolean | #### Example request ```bash curl "https://domscan.net/v1/coverage?live=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/coverage?live=1"); const data = await response.json(); console.log(data); ``` ```python import requests response = requests.get( "https://domscan.net/v1/coverage?live=1", ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/coverage?live=1", nil) if err != nil { panic(err) } resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/coverage?live=1") request = Net::HTTP::Get.new(uri) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "gtlds": [ "example" ], "cctlds": [ "example" ], "total_tlds": 1, "all_tlds": [ "com" ], "rdap_health": [ { "tld": "com", "endpoint": "https://example.com", "measurement_status": "single_probe", "ok": true, "p50_ms": 1.5, "error_rate": 0 } ], "bootstrap_source": "iana", "bootstrap_last_updated": "2026-08-27T12:00:00Z", "meta": { "served_by": "example", "bootstrap_ttl_s": 1, "live": false } } ``` #### HTTP status codes - `200` OK - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-suggestions # Domain Suggestions API Get AI-powered domain name suggestions based on your keywords, brand, or business description. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-suggestions) ## Operations GET `/v1/suggest` [View API reference](https://domscan.net/docs/products/domain-suggestions#suggestDomains) ## GET `/v1/suggest` Operation: `suggestDomains` Credits and authentication: 2-5 Authentication required GET /v1/suggest Credits: 2-5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | keywords | string | required | | tlds | string | optional | | style | string Allowed values `brandable`, `keyword-rich`, `short`, `pronounceable`, `techy`, `playful`, `professional`, `minimal` Default `brandable` | optional | | industry | string Allowed values `tech`, `finance`, `health`, `ecommerce`, `education`, `media`, `saas`, `crypto`, `ai`, `gaming` | optional | | language | string Allowed values `en`, `zh`, `es`, `ja`, `de`, `fr`, `pt`, `it`, `ko`, `ru`, `ar`, `hi`, `bn`, `id`, `ms`, `th`, `vi`, `tr`, `pl`, `nl`, `sv`, `da`, `no`, `fi`, `el`, `cs`, `hu`, `ro`, `uk`, `he` Default `en` | optional | | limit | integer Default `20` | optional | | check | boolean Default `true` | optional | #### Response fields | Field | Type | | --- | --- | | `suggestions[]` | object[] | | `suggestions[]` | object | | `suggestions[].name` | string | | `suggestions[].domain` | string | | `suggestions[].tld` | string | | `suggestions[].score` | integer | | `suggestions[].available` | boolean \| null | | `suggestions[].method` | string | | `suggestions[].styles[]` | string[] | | `suggestions[].checked_at` | string | | `keywords[]` | string[] | | `tlds[]` | string[] | | `styles[]` | string[] | | `industry` | string \| null | | `language` | string | | `generated_count` | integer | | `available_count` | integer \| null | | `generation_summary` | object | | `generation_summary.requested_limit` | integer | | `generation_summary.candidate_count` | integer | | `generation_summary.returned_count` | integer | | `generation_summary.availability_checked` | boolean | | `generation_summary.availability_check_count` | integer | | `generation_summary.available_count` | integer \| null | | `generation_summary.tld_count` | integer | | `generation_summary.language` | string | | `generation_summary.method_counts` | object | | `generation_summary.style_counts` | object | | `generation_summary.top_method` | string \| null | | `generation_summary.average_score` | integer \| null | | `meta` | object | | `meta.total_generated` | integer | | `meta.available_count` | integer | | `meta.generation_ms` | integer | | `meta.availability_check_ms` | integer | | `meta.total_ms` | integer | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/suggest?keywords=crypto%2Cwallet%2Cfinance&tlds=com%2Cio&style=brandable&industry=tech&language=es&limit=25&check=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/suggest?keywords=crypto%2Cwallet%2Cfinance&tlds=com%2Cio&style=brandable&industry=tech&language=es&limit=25&check=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/suggest?keywords=crypto%2Cwallet%2Cfinance&tlds=com%2Cio&style=brandable&industry=tech&language=es&limit=25&check=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/suggest?keywords=crypto%2Cwallet%2Cfinance&tlds=com%2Cio&style=brandable&industry=tech&language=es&limit=25&check=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/suggest?keywords=crypto%2Cwallet%2Cfinance&tlds=com%2Cio&style=brandable&industry=tech&language=es&limit=25&check=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "suggestions": [ { "name": "brandpilot", "domain": "brandpilot.io", "tld": "io", "score": 86, "available": true, "method": "combination" }, { "name": "getbrand", "domain": "getbrand.com", "tld": "com", "score": 78, "available": false, "method": "prefix" }, { "name": "pilotbrand", "domain": "pilotbrand.ai", "tld": "ai", "score": 74, "available": null, "method": "combination" } ], "keywords": [ "brand", "pilot" ], "tlds": [ "com", "io", "ai" ], "styles": [ "brandable", "keyword-rich", "short", "pronounceable" ], "language": "en", "generated_count": 12, "available_count": 4, "generation_summary": { "requested_limit": 3, "candidate_count": 12, "returned_count": 3, "availability_checked": true, "availability_check_count": 9, "available_count": 4, "tld_count": 3, "language": "en", "method_counts": { "combination": 2, "prefix": 1 }, "style_counts": { "brandable": 2, "keyword-rich": 2, "pronounceable": 1 }, "top_method": "combination", "average_score": 79 }, "meta": { "generation_ms": 6 } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-valuation # Domain Valuation API Estimate the market value of a domain based on multiple factors including length, keywords, TLD, and market trends. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-valuation) ## Operations GET `/v1/value` [View API reference](https://domscan.net/docs/products/domain-valuation#getDomainValue) POST `/v1/value/bulk` [View API reference](https://domscan.net/docs/products/domain-valuation#bulkDomainValue) ## GET `/v1/value` Operation: `getDomainValue` Credits and authentication: 2 Authentication required GET /v1/value Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `label` | string | | `tld` | string | | `estimate` | object | | `estimate.low` | integer | | `estimate.mid` | integer | | `estimate.high` | integer | | `estimate.currency` | string | | `factors` | object | | `factors.length` | integer | | `factors.lengthMultiplier` | number | | `factors.tld` | string | | `factors.tldTier` | string | | `factors.tldBase` | integer | | `factors.hasHyphens` | boolean | | `factors.hasNumbers` | boolean | | `factors.lettersOnly` | boolean | | `factors.isPremiumWord` | boolean | | `factors.isDictionaryWord` | boolean | | `factors.isBrandable` | boolean | | `factors.isNumericPattern` | boolean | | `factors.isLetterPattern` | boolean | | `factors.pronounceability` | number | | `factors.memorability` | number | | `factors.spellingDifficulty` | number | | `factors.isAcronym` | boolean | | `factors.hasCommonEnding` | boolean | | `factors.syllableCount` | integer | | `comparables[]` | object[] | | `comparables[]` | object | | `comparables[].category` | string | | `comparables[].typical_range` | object | | `comparables[].typical_range.low` | integer | | `comparables[].typical_range.high` | integer | | `comparables[].examples[]` | string[] | | `comparables[].relevance` | number | | `confidence` | number | | `valuation_summary` | object | | `valuation_summary.model_scope` | string | | `valuation_summary.confidence` | number | | `valuation_summary.confidence_label` | string | | `valuation_summary.range_source` | string | | `valuation_summary.range_width` | string | | `valuation_summary.comparable_count` | integer | | `valuation_summary.primary_comparable_category` | string \| null | | `valuation_summary.primary_comparable_position` | string \| null | | `valuation_summary.positive_driver_count` | integer | | `valuation_summary.negative_driver_count` | integer | | `valuation_summary.liquidity_band` | string | | `valuation_summary.tld_tier` | string | | `valuation_summary.renewal_price_awareness` | object | | `valuation_summary.renewal_price_awareness.uses_tld_base` | boolean | | `valuation_summary.renewal_price_awareness.tld_base_usd` | integer | | `valuation_summary.renewal_price_awareness.registrar_specific_prices_included` | boolean | | `valuation_summary.risk_flags[]` | string[] | | `analysis` | object | | `analysis.scope` | string | | `analysis.excludes[]` | string[] | | `analysis.range_source` | string | | `analysis.range_width` | string | | `analysis.confidence_label` | string | | `analysis.primary_comparable_category` | string \| null | | `analysis.primary_comparable_range` | object | | `analysis.primary_comparable_range.low` | integer | | `analysis.primary_comparable_range.high` | integer | | `analysis.primary_comparable_range.position` | string | | `analysis.primary_comparable_range.relative_position` | number | | `analysis.out_of_distribution` | boolean | | `analysis.out_of_distribution_reasons[]` | string[] | | `analysis.positive_factors[]` | string[] | | `analysis.negative_factors[]` | string[] | | `methodology` | string | | `meta` | object | | `meta.served_by` | string | | `meta.disclaimer` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/value?domain=empresa.ind.br" ``` ```javascript const response = await fetch("https://domscan.net/v1/value?domain=empresa.ind.br", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/value?domain=empresa.ind.br", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/value?domain=empresa.ind.br", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/value?domain=empresa.ind.br") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "label": "example", "tld": "com", "estimate": { "low": 10845, "mid": 16012, "high": 34266, "currency": "USD" }, "factors": { "length": 7, "lengthMultiplier": 2, "tld": "com", "tldTier": "premium", "tldBase": 1500, "hasHyphens": false, "hasNumbers": false, "lettersOnly": true, "isPremiumWord": false, "isDictionaryWord": false, "isBrandable": true, "isNumericPattern": false, "isLetterPattern": false, "pronounceability": 0.87, "memorability": 0.87, "spellingDifficulty": 0.8, "isAcronym": false, "hasCommonEnding": false, "syllableCount": 3 }, "comparables": [ { "category": ".com brandable 5-7 chars", "typical_range": { "low": 2000, "high": 80000 }, "examples": [ "Lyft ($225K), Uber ($100K est.), Klarna" ], "relevance": 0.76 } ], "confidence": 0.66, "analysis": { "scope": "intrinsic_domain_value", "excludes": [ "website_traffic", "revenue", "brand_equity", "buyer-specific strategic premium" ], "range_source": "blended", "range_width": "moderate", "confidence_label": "medium", "primary_comparable_category": ".com brandable 5-7 chars", "primary_comparable_range": { "low": 2000, "high": 80000, "position": "mid", "relative_position": 0.56 }, "out_of_distribution": false, "out_of_distribution_reasons": [], "positive_factors": [ "Premium .com market liquidity", "Pronounceable and brandable label", "Anchored by .com brandable 5-7 chars comparables" ], "negative_factors": [] }, "methodology": "Algorithmic intrinsic-domain estimate anchored to public domain sales data. It excludes website traffic, revenue, and business/company value, and uses length, TLD tier, character composition, brandability, semantic segmentation, and market comparables from NameBio/DNJournal-style buckets.", "valuation_summary": { "model_scope": "intrinsic_domain_value", "confidence": 0.66, "confidence_label": "medium", "range_source": "blended", "range_width": "moderate", "comparable_count": 1, "primary_comparable_category": ".com brandable 5-7 chars", "primary_comparable_position": "mid", "positive_driver_count": 3, "negative_driver_count": 0, "liquidity_band": "high", "tld_tier": "premium", "renewal_price_awareness": { "uses_tld_base": true, "tld_base_usd": 1500, "registrar_specific_prices_included": false }, "risk_flags": [] }, "meta": { "served_by": "pop=MAD country=ES", "disclaimer": "This is an algorithmic estimate based on domain characteristics. Actual market value may vary significantly based on buyer demand, comparable sales, and market conditions." } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/value/bulk` Operation: `bulkDomainValue` Credits and authentication: 2 Authentication required POST /v1/value/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `results[].domain` | string | | `results[].label` | string | | `results[].tld` | string | | `results[].estimate` | object | | `results[].estimate.low` | integer | | `results[].estimate.mid` | integer | | `results[].estimate.high` | integer | | `results[].estimate.currency` | string | | `results[].factors` | object | | `results[].factors.length` | integer | | `results[].factors.lengthMultiplier` | number | | `results[].factors.tld` | string | | `results[].factors.tldTier` | string | | `results[].factors.tldBase` | integer | | `results[].factors.hasHyphens` | boolean | | `results[].factors.hasNumbers` | boolean | | `results[].factors.lettersOnly` | boolean | | `results[].factors.isPremiumWord` | boolean | | `results[].factors.isDictionaryWord` | boolean | | `results[].factors.isBrandable` | boolean | | `results[].factors.isNumericPattern` | boolean | | `results[].factors.isLetterPattern` | boolean | | `results[].factors.pronounceability` | number | | `results[].factors.memorability` | number | | `results[].factors.spellingDifficulty` | number | | `results[].factors.isAcronym` | boolean | | `results[].factors.hasCommonEnding` | boolean | | `results[].factors.syllableCount` | integer | | `results[].comparables[]` | object[] | | `results[].comparables[]` | object | | `results[].comparables[].category` | string | | `results[].comparables[].typical_range` | object | | `results[].comparables[].typical_range.low` | integer | | `results[].comparables[].typical_range.high` | integer | | `results[].comparables[].examples[]` | string[] | | `results[].comparables[].relevance` | number | | `results[].confidence` | number | | `results[].valuation_summary` | object | | `results[].valuation_summary.model_scope` | string | | `results[].valuation_summary.confidence` | number | | `results[].valuation_summary.confidence_label` | string | | `results[].valuation_summary.range_source` | string | | `results[].valuation_summary.range_width` | string | | `results[].valuation_summary.comparable_count` | integer | | `results[].valuation_summary.primary_comparable_category` | string \| null | | `results[].valuation_summary.primary_comparable_position` | string \| null | | `results[].valuation_summary.positive_driver_count` | integer | | `results[].valuation_summary.negative_driver_count` | integer | | `results[].valuation_summary.liquidity_band` | string | | `results[].valuation_summary.tld_tier` | string | | `results[].valuation_summary.renewal_price_awareness` | object | | `results[].valuation_summary.renewal_price_awareness.uses_tld_base` | boolean | | `results[].valuation_summary.renewal_price_awareness.tld_base_usd` | integer | | `results[].valuation_summary.renewal_price_awareness.registrar_specific_prices_included` | boolean | | `results[].valuation_summary.risk_flags[]` | string[] | | `results[].analysis` | object | | `results[].analysis.scope` | string | | `results[].analysis.excludes[]` | string[] | | `results[].analysis.range_source` | string | | `results[].analysis.range_width` | string | | `results[].analysis.confidence_label` | string | | `results[].analysis.primary_comparable_category` | string \| null | | `results[].analysis.primary_comparable_range` | object | | `results[].analysis.primary_comparable_range.low` | integer | | `results[].analysis.primary_comparable_range.high` | integer | | `results[].analysis.primary_comparable_range.position` | string | | `results[].analysis.primary_comparable_range.relative_position` | number | | `results[].analysis.out_of_distribution` | boolean | | `results[].analysis.out_of_distribution_reasons[]` | string[] | | `results[].analysis.positive_factors[]` | string[] | | `results[].analysis.negative_factors[]` | string[] | | `results[].methodology` | string | | `results[].meta` | object | | `results[].meta.served_by` | string | | `results[].meta.disclaimer` | string | | `meta` | object | | `meta.served_by` | string | | `meta.total` | integer | | `meta.disclaimer` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/value/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "startup.io", "brand.ai" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/value/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "startup.io", "brand.ai" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/value/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "startup.io", "brand.ai", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "startup.io", "brand.ai" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/value/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/value/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "startup.io", "brand.ai" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "domain": "example.com", "label": "example", "tld": "com", "estimate": { "low": 1, "mid": 1, "high": 1, "currency": "USD" }, "factors": { "length": 1, "lengthMultiplier": 0.5, "tld": "com", "tldTier": "premium", "tldBase": 1, "hasHyphens": false, "hasNumbers": false, "lettersOnly": false, "isPremiumWord": false, "isDictionaryWord": false, "isBrandable": false, "isNumericPattern": false, "isLetterPattern": false, "pronounceability": 0.5, "memorability": 0.5, "spellingDifficulty": 0.5, "isAcronym": false, "hasCommonEnding": false, "syllableCount": 1 }, "comparables": [ { "category": "example", "typical_range": { "low": 1, "high": 1 }, "examples": [ "example" ], "relevance": 0.5 } ], "confidence": 0.85, "valuation_summary": { "model_scope": "intrinsic_domain_value", "confidence": 0.85, "confidence_label": "low", "range_source": "heuristic", "range_width": "narrow", "comparable_count": 1, "primary_comparable_category": "example", "primary_comparable_position": "lower", "positive_driver_count": 1, "negative_driver_count": 1, "liquidity_band": "low", "tld_tier": "premium", "renewal_price_awareness": { "uses_tld_base": false, "tld_base_usd": 1, "registrar_specific_prices_included": false }, "risk_flags": [ "example" ] }, "analysis": { "scope": "intrinsic_domain_value", "excludes": [ "example" ], "range_source": "heuristic", "range_width": "narrow", "confidence_label": "low", "primary_comparable_category": "example", "primary_comparable_range": { "low": 1, "high": 1, "position": "lower", "relative_position": 0.5 }, "out_of_distribution": false, "out_of_distribution_reasons": [ "example" ], "positive_factors": [ "example" ], "negative_factors": [ "example" ] }, "methodology": "example", "meta": { "served_by": "example", "disclaimer": "example" } } ], "meta": { "served_by": "example", "total": 1, "disclaimer": "example" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-health # Domain Health API Comprehensive health check for a domain including DNS, SSL, website reachability, and security headers. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-health-checker) ## Operations GET `/v1/health` [View API reference](https://domscan.net/docs/products/domain-health#getDomainHealth) GET `/v1/health/quick` [View API reference](https://domscan.net/docs/products/domain-health#getQuickHealth) ## GET `/v1/health` Operation: `getDomainHealth` Credits and authentication: 3 Authentication required GET /v1/health Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | details | boolean Default `true` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `health_score` | integer | | `grade` | string | | `checks` | object | | `checks.dns_configured` | boolean | | `checks.ssl_valid` | boolean | | `checks.email_deliverable` | boolean | | `checks.blacklist_status` | string | | `checks.age_years` | integer \| null | | `checks.registration_stable` | boolean | | `checks.dnssec_enabled` | boolean | | `enriched` | object | | `enriched.tls` | object | | `enriched.tls.grade` | string | | `enriched.tls.protocol` | string \| null | | `enriched.tls.cipher` | string \| null | | `enriched.tls.chain_valid` | boolean | | `enriched.tls.days_to_expiry` | integer | | `enriched.tls.hostname_match` | boolean \| null | | `enriched.tls.ocsp_stapling` | boolean | | `enriched.tls.grade_reasons[]` | string[] | | `enriched.http_versions` | object | | `enriched.http_versions.http1_1` | boolean | | `enriched.http_versions.http2` | boolean | | `enriched.http_versions.http3` | boolean | | `enriched.http_versions.alt_svc` | string \| null | | `enriched.http_versions.http3_advertised` | boolean | | `enriched.http_versions.alt_svc_protocols[]` | string[] | | `enriched.http_versions.curl_http3_supported` | boolean | | `enriched.http_versions.h2_alpn_accepted` | string \| null | | `enriched.http_versions.h3_alpn_accepted` | string \| null | | `enriched.hsts` | object | | `enriched.hsts.reachable` | boolean | | `enriched.hsts.final_url` | string \| null | | `enriched.hsts.status_code` | integer \| null | | `enriched.hsts.header_present` | boolean | | `enriched.hsts.hsts_header` | string \| null | | `enriched.hsts.max_age` | integer \| null | | `enriched.hsts.include_subdomains` | boolean \| null | | `enriched.hsts.preload_directive` | boolean \| null | | `enriched.hsts.preload_eligible` | boolean | | `enriched.hsts.preload_status` | string \| null | | `enriched.hsts.preloaded_domain` | string \| null | | `enriched.hsts.preload_bulk` | boolean \| null | | `enriched.hsts.issues[]` | string[] | | `enriched.hsts.errors[]` | string[] | | `enriched.smtp` | object | | `enriched.smtp.host` | string | | `enriched.smtp.port` | integer | | `enriched.smtp.reachable` | boolean | | `enriched.smtp.tls_mode` | string | | `enriched.smtp.tls_negotiated` | boolean | | `enriched.smtp.tls_protocol` | string | | `enriched.smtp.tls_cipher` | string | | `enriched.smtp.starttls_offered` | boolean \| null | | `enriched.smtp.banner` | string | | `enriched.smtp.error` | string | | `enriched.smtp.fcrdns` | object | | `enriched.smtp.fcrdns.addresses[]` | string[] | | `enriched.smtp.fcrdns.ptr_hostnames[]` | string[] | | `enriched.smtp.fcrdns.all_forward_confirmed` | boolean | | `enriched.smtp.fcrdns.confirmed_addresses[]` | string[] | | `enriched.smtp.fcrdns.unconfirmed_addresses[]` | string[] | | `warnings[]` | string[] | | `recommendations[]` | string[] | | `component_summary` | object | | `component_summary.score` | integer | | `component_summary.grade` | string | | `component_summary.check_count` | integer | | `component_summary.passed_count` | integer | | `component_summary.failed_count` | integer | | `component_summary.warning_count` | integer | | `component_summary.recommendation_count` | integer | | `component_summary.confidence` | string | | `component_summary.dns_ok` | boolean | | `component_summary.https_ok` | boolean | | `component_summary.email_ok` | boolean | | `component_summary.blacklist_status` | string | | `component_summary.dnssec_enabled` | boolean | | `component_summary.enriched_section_count` | integer | | `component_summary.enriched_sections[]` | string[] | | `details` | object | | `health_checks[]` | object[] | | `health_checks[]` | object | | `health_checks[].category` | string | | `health_checks[].name` | string | | `health_checks[].passed` | boolean | | `health_checks[].score` | integer | | `health_checks[].weight` | integer | | `health_checks[].details` | string \| null | | `checked_at` | string | | `meta` | object | | `meta.check_duration_ms` | integer | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/health?domain=example.com&details=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/health?domain=example.com&details=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/health?domain=example.com&details=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/health?domain=example.com&details=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/health?domain=example.com&details=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "cloudflare.com", "health_score": 94, "grade": "A", "checks": { "dns_configured": true, "ssl_valid": true, "email_deliverable": true, "blacklist_status": "clean", "age_years": 15, "registration_stable": true, "dnssec_enabled": true }, "enriched": { "tls": { "grade": "A+", "protocol": "TLSv1.3", "cipher": "TLS_AES_256_GCM_SHA384", "chain_valid": true, "days_to_expiry": 72, "hostname_match": true, "ocsp_stapling": true, "grade_reasons": [ "TLS 1.3 enabled", "Valid certificate chain" ] }, "http_versions": { "http1_1": true, "http2": true, "http3": true, "alt_svc": "h3=\":443\"; ma=86400", "http3_advertised": true, "alt_svc_protocols": [ "h3" ], "curl_http3_supported": true, "h2_alpn_accepted": "h2", "h3_alpn_accepted": "h3" }, "hsts": { "reachable": true, "final_url": "https://cloudflare.com/", "status_code": 200, "header_present": true, "hsts_header": "max-age=31536000; includeSubDomains", "max_age": 31536000, "include_subdomains": true, "preload_directive": false, "preload_eligible": true, "preload_status": "preloaded", "preloaded_domain": "cloudflare.com", "preload_bulk": false, "issues": [ "missing preload directive" ], "errors": [] } }, "warnings": [], "recommendations": [ "Publish the HSTS preload directive if you want preload-list eligibility." ], "checked_at": "2026-04-18T21:00:00Z", "details": { "dns": { "has_a_record": true, "has_aaaa_record": true, "has_nameservers": true, "has_mx_record": true, "nameservers": [ "ns3.cloudflare.com", "ns5.cloudflare.com" ], "mx_records": [ "route1.mx.cloudflare.net" ], "a_records": [ "104.16.132.229", "104.16.133.229" ], "aaaa_records": [ "2606:4700::6810:84e5", "2606:4700::6810:85e5" ] }, "ssl": { "https_works": true, "certificate_valid": true, "days_until_expiry": 72, "issuer": "Google Trust Services" }, "email": { "has_mx": true, "has_spf": true, "has_dmarc": true, "has_dkim_selector": true, "spf_record": "v=spf1 include:_spf.google.com ~all", "dmarc_policy": "reject", "mx_hosts": [ "route1.mx.cloudflare.net" ] }, "security": { "dnssec_enabled": true, "has_caa_record": true, "caa_issuers": [ "digicert.com", "letsencrypt.org" ], "http_to_https_redirect": true, "has_security_txt": true, "security_txt_fields": [ "Contact", "Expires", "Preferred-Languages" ], "security_headers": { "has_hsts": true, "hsts_max_age": 31536000, "has_csp": true, "has_x_frame_options": true, "has_x_content_type_options": true, "has_referrer_policy": true, "has_permissions_policy": true, "score": 92 } }, "age": { "registration_date": "2010-07-06T00:00:00Z", "expiration_date": "2030-07-06T00:00:00Z", "last_updated": "2025-07-06T00:00:00Z", "age_days": 5766, "age_years": 15, "days_until_expiry": 1540, "registrar": "Cloudflare Registrar" }, "blacklist": { "clean": true, "status": "clean", "listed_on": [], "checked_lists": [ "spamhaus", "surbl" ], "domain_listed_on": [], "ip_listed_on": [], "check_type": "mixed" } }, "health_checks": [ { "category": "dns", "name": "Authoritative DNS records present", "passed": true, "score": 100, "weight": 15 } ], "meta": { "check_duration_ms": 248, "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/health/quick` Operation: `getQuickHealth` Credits and authentication: 1 Authentication required GET /v1/health/quick Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `dns_ok` | boolean \| null | | `https_ok` | boolean \| null | | `dns_complete` | boolean | | `checked_at` | string | | `confidence` | object | | `confidence.checks_run[]` | string[] | | `confidence.passed_count` | integer | | `confidence.failed_count` | integer | | `confidence.unknown_count` | integer | | `confidence.confidence` | string | | `confidence.dns_ok` | boolean \| null | | `confidence.https_ok` | boolean \| null | | `meta` | object | | `meta.check_duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/health/quick?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/health/quick?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/health/quick?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/health/quick?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/health/quick?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "dns_ok": true, "https_ok": true, "checked_at": "2026-04-18T21:00:00Z", "meta": { "check_duration_ms": 89 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `500` Server Error ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-lifecycle # Domain Lifecycle API Get detailed lifecycle information for a domain including registration, expiration, and status history. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-lifecycle-api) ## Operations GET `/v1/lifecycle` [View API reference](https://domscan.net/docs/products/domain-lifecycle#getDomainLifecycle) ## GET `/v1/lifecycle` Operation: `getDomainLifecycle` Credits and authentication: 2 Authentication required GET /v1/lifecycle Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `tld` | string | | `registered` | string | | `expires` | string | | `updated` | string | | `age_days` | integer | | `expires_in_days` | integer | | `phase` | string | | `status_flags[]` | string[] | | `status` | string | | `events[]` | object[] | | `events[]` | object | | `events[].action` | string | | `events[].date` | string | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/lifecycle?domain=bbc.co.uk" ``` ```javascript const response = await fetch("https://domscan.net/v1/lifecycle?domain=bbc.co.uk", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/lifecycle?domain=bbc.co.uk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/lifecycle?domain=bbc.co.uk", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/lifecycle?domain=bbc.co.uk") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "bbc.co.uk", "tld": "co.uk", "registered": "1997-08-01T00:00:00Z", "expires": "2026-08-01T00:00:00Z", "updated": "2024-08-01T00:00:00Z", "age_days": 10515, "expires_in_days": 474, "phase": "active", "status_flags": [ "clientTransferProhibited", "serverTransferProhibited" ], "status": "clientTransferProhibited serverTransferProhibited", "events": [ { "action": "registration", "date": "1997-08-01T00:00:00Z" }, { "action": "last changed", "date": "2024-08-01T00:00:00Z" }, { "action": "expiration", "date": "2026-08-01T00:00:00Z" } ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway - `503` Service Unavailable ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-compare # Domain Compare API Compare multiple domains side by side on various metrics including valuation, health, and SEO factors. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-compare) ## Operations GET `/v1/compare` [View API reference](https://domscan.net/docs/products/domain-compare#compareDomains) ## GET `/v1/compare` Operation: `compareDomains` Credits and authentication: 3 Authentication required GET /v1/compare Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domains | string | required | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `domains[]` | object[] | | `domains[]` | object | | `domains[].domain` | string | | `domains[].tld` | string | | `domains[].available` | boolean \| null | | `domains[].registered_at` | string \| null | | `domains[].expires_at` | string \| null | | `domains[].valuation` | object | | `domains[].valuation.estimate_usd` | number | | `domains[].valuation.confidence` | number | | `domains[].valuation.factors` | object | | `domains[].valuation.factors.length` | integer | | `domains[].valuation.factors.lengthMultiplier` | number | | `domains[].valuation.factors.tld` | string | | `domains[].valuation.factors.tldTier` | string | | `domains[].valuation.factors.tldBase` | integer | | `domains[].valuation.factors.hasHyphens` | boolean | | `domains[].valuation.factors.hasNumbers` | boolean | | `domains[].valuation.factors.lettersOnly` | boolean | | `domains[].valuation.factors.isPremiumWord` | boolean | | `domains[].valuation.factors.isDictionaryWord` | boolean | | `domains[].valuation.factors.isBrandable` | boolean | | `domains[].valuation.factors.isNumericPattern` | boolean | | `domains[].valuation.factors.isLetterPattern` | boolean | | `domains[].valuation.factors.pronounceability` | number | | `domains[].valuation.factors.memorability` | number | | `domains[].valuation.factors.spellingDifficulty` | number | | `domains[].valuation.factors.isAcronym` | boolean | | `domains[].valuation.factors.hasCommonEnding` | boolean | | `domains[].valuation.factors.syllableCount` | integer | | `domains[].valuation.estimate` | object | | `domains[].valuation.estimate.low` | number | | `domains[].valuation.estimate.mid` | number | | `domains[].valuation.estimate.high` | number | | `domains[].valuation.estimate.currency` | string | | `domains[].valuation.analysis` | object | | `domains[].valuation.analysis.scope` | string | | `domains[].valuation.analysis.range_source` | string | | `domains[].valuation.analysis.range_width` | string | | `domains[].valuation.analysis.confidence_label` | string | | `domains[].valuation.analysis.out_of_distribution` | boolean | | `domains[].valuation.analysis.out_of_distribution_reasons[]` | string[] | | `domains[].valuation.analysis.positive_factors[]` | string[] | | `domains[].valuation.analysis.negative_factors[]` | string[] | | `domains[].score` | object | | `domains[].score.overall` | number | | `domains[].score.length` | number | | `domains[].score.pronounceability` | number | | `domains[].score.memorability` | number | | `domains[].score.brandability` | number | | `domains[].tld_info` | object | | `domains[].tld_info.type` | string | | `domains[].tld_info.trust_tier` | string | | `domains[].tld_info.popularity_rank` | integer \| null | | `domains[].recommendation_rank` | integer \| null | | `domains[].recommendation_reason` | string \| null | | `recommendation` | object | | `recommendation.best_available` | string \| null | | `recommendation.best_overall` | string \| null | | `recommendation.best_value` | string \| null | | `recommendation.reasoning` | string | | `decision_summary` | object | | `decision_summary.compared_count` | integer | | `decision_summary.best_overall` | string \| null | | `decision_summary.best_available` | string \| null | | `decision_summary.runner_up` | string \| null | | `decision_summary.rank_margin` | integer \| null | | `decision_summary.score_margin` | integer \| null | | `decision_summary.value_margin_usd` | number \| null | | `decision_summary.availability_used` | boolean | | `decision_summary.winning_factor` | string \| null | | `decision_summary.tie_breaker` | string \| null | | `meta` | object | | `meta.compared_count` | integer | | `meta.available_count` | integer | | `meta.total_ms` | integer | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/compare?domains=startup.com%2Cstartup.io%2Cstartup.ai" ``` ```javascript const response = await fetch("https://domscan.net/v1/compare?domains=startup.com%2Cstartup.io%2Cstartup.ai", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/compare?domains=startup.com%2Cstartup.io%2Cstartup.ai", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/compare?domains=startup.com%2Cstartup.io%2Cstartup.ai", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/compare?domains=startup.com%2Cstartup.io%2Cstartup.ai") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domains": [ { "domain": "startup.io", "tld": "io", "available": true, "valuation": { "estimate_usd": 2500, "confidence": 0.7, "estimate": { "low": 1400, "mid": 2500, "high": 4100, "currency": "USD" }, "analysis": { "scope": "intrinsic_domain_value", "range_source": "anchored", "range_width": "moderate", "confidence_label": "medium", "out_of_distribution": false, "out_of_distribution_reasons": [], "positive_factors": [ "Strong .IO aftermarket demand" ], "negative_factors": [ "Narrower buyer pool than .com" ] } }, "score": { "overall": 85, "brandability": 90 }, "tld_info": { "type": "ccTLD", "trust_tier": "premium", "popularity_rank": 4 }, "recommendation_rank": 85, "recommendation_reason": "available for registration, premium .io TLD, excellent brand score" } ], "recommendation": { "best_available": "startup.io", "best_overall": "startup.com", "best_value": "startup.ai", "reasoning": "startup.io is recommended: available for registration, premium .io TLD, excellent brand score" }, "decision_summary": { "compared_count": 3, "best_overall": "startup.com", "best_available": "startup.io", "runner_up": "startup.io", "rank_margin": 4, "score_margin": 2, "value_margin_usd": 1500, "availability_used": true, "winning_factor": "valuation", "tie_breaker": "higher_valuation" }, "meta": { "compared_count": 3, "available_count": 2, "total_ms": 84 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/tld-intelligence # TLD Intelligence API Get detailed intelligence about a TLD including pricing, restrictions, registrar support, and usage statistics. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/tld-intelligence) ## Operations GET `/v1/tlds` [View API reference](https://domscan.net/docs/products/tld-intelligence#getTlds) GET `/v1/tlds/:tld` [View API reference](https://domscan.net/docs/products/tld-intelligence#getTldDetail) ## GET `/v1/tlds` Operation: `getTlds` Credits and authentication: Free Authentication optional GET /v1/tlds Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | type | string Allowed values `gtld`, `cctld`, `new-gtld`, `idn` | optional | | trust_tier | string Allowed values `premium`, `standard`, `economy`, `suspicious` | optional | | use_case | string | optional | #### Response fields | Field | Type | | --- | --- | | `tlds[]` | object[] | | `tlds[]` | object | | `tlds[].tld` | string | | `tlds[].type` | string | | `tlds[].name` | string | | `tlds[].rdap_supported` | boolean | | `tlds[].trust_tier` | string | | `tlds[].popularity_rank` | integer | | `tlds[].registration_usd` | number | | `total` | integer | | `by_type` | object | | `by_type.gTLD` | integer | | `by_type.ccTLD` | integer | | `by_type.newTLD` | integer | | `by_type.idn` | integer | | `by_trust_tier` | object | | `by_trust_tier.premium` | integer | | `by_trust_tier.standard` | integer | | `by_trust_tier.economy` | integer | | `use_case` | string | | `meta` | object | #### Example request ```bash curl "https://domscan.net/v1/tlds?type=gtld&trust_tier=premium&use_case=startup" ``` ```javascript const response = await fetch("https://domscan.net/v1/tlds?type=gtld&trust_tier=premium&use_case=startup"); const data = await response.json(); console.log(data); ``` ```python import requests response = requests.get( "https://domscan.net/v1/tlds?type=gtld&trust_tier=premium&use_case=startup", ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tlds?type=gtld&trust_tier=premium&use_case=startup", nil) if err != nil { panic(err) } ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tlds?type=gtld&trust_tier=premium&use_case=startup") request = Net::HTTP::Get.new(uri) #### Example response ```json { "tlds": [ { "tld": "com", "type": "gTLD", "name": "example", "rdap_supported": false, "trust_tier": "premium", "popularity_rank": 1, "registration_usd": 0.5 } ], "total": 1, "by_type": { "gTLD": 1, "ccTLD": 1, "newTLD": 1, "idn": 1 }, "by_trust_tier": { "premium": 1, "standard": 1, "economy": 1 }, "use_case": "example", "meta": {} } ``` #### HTTP status codes - `200` OK - `429` Too Many Requests ## GET `/v1/tlds/:tld` Operation: `getTldDetail` Credits and authentication: 1 Authentication required GET /v1/tlds/:tld Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | tld | string | required | #### Response fields | Field | Type | | --- | --- | | `tld` | string | | `type` | string | | `name` | string | | `description` | string | | `introduced` | integer | | `operator` | string \| null | | `country` | string \| null | | `restrictions` | string | | `rdap_supported` | boolean | | `rdap_endpoint` | string \| null | | `idn_supported` | boolean | | `dnssec_supported` | boolean | | `pricing` | object | | `pricing.registration_usd` | number | | `pricing.renewal_usd` | number | | `pricing.transfer_usd` | number | | `pricing.currency` | string | | `pricing.source` | string | | `popularity` | object | | `popularity.rank` | integer | | `popularity.tier` | string | | `popularity.use_cases[]` | string[] | | `trust` | object | | `trust.score` | number | | `trust.tier` | string | | `trust.notes` | string \| null | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tlds/com" ``` ```javascript const response = await fetch("https://domscan.net/v1/tlds/com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tlds/com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tlds/com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tlds/com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "tld": "com", "type": "gTLD", "name": "Commercial", "description": "The most popular and trusted domain extension worldwide", "introduced": 1985, "operator": "Verisign", "restrictions": "None - open registration", "rdap_supported": true, "rdap_endpoint": "https://rdap.verisign.com/com/v1/", "idn_supported": true, "dnssec_supported": true, "pricing": { "registration_usd": 12, "renewal_usd": 12, "transfer_usd": 12, "currency": "USD", "source": "market_average" }, "popularity": { "rank": 1, "tier": "top10", "use_cases": [ "business", "personal", "startup", "enterprise", "tech", "e-commerce", "blog", "portfolio" ] }, "trust": { "score": 100, "tier": "premium", "notes": "Most trusted TLD globally" }, "meta": { "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `402` Payment Required - `404` Not Found - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-pricing # Domain Pricing API Get registration and renewal prices for domains across registrars. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-pricing-api) ## Operations GET `/v1/prices` [View API reference](https://domscan.net/docs/products/domain-pricing#getPrices) POST `/v1/prices/bulk` [View API reference](https://domscan.net/docs/products/domain-pricing#bulkPricing) GET `/v1/prices/tld/:tld` [View API reference](https://domscan.net/docs/products/domain-pricing#getTldPricing) GET `/v1/prices/registrars` [View API reference](https://domscan.net/docs/products/domain-pricing#getRegistrars) GET `/v1/prices/compare` [View API reference](https://domscan.net/docs/products/domain-pricing#comparePrices) GET `/v1/pricing` [View API reference](https://domscan.net/docs/products/domain-pricing#getPricingInfo) ## GET `/v1/prices` Operation: `getPrices` Credits and authentication: 0-1 Authentication required GET /v1/prices Credits: 0-1/pair #### Query parameters | Parameter | Type | required | | --- | --- | --- | | tlds | string | optional | | registrars | string | optional | | skip_cache | boolean Default `false` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.supportedTlds[]` | string[] | | `data.count` | integer | | `data.hint` | string | | `data.results[]` | object[] | | `data.results[]` | object | | `data.results[].tld` | string | | `data.results[].prices[]` | object[] | | `data.results[].prices[]` | object | | `data.results[].prices[].registrar` | string | | `data.results[].prices[].registrarName` | string | | `data.results[].prices[].register` | number \| null | | `data.results[].prices[].renew` | number \| null | | `data.results[].prices[].transfer` | number \| null | | `data.results[].prices[].currency` | string | | `data.results[].prices[].promoPrice` | number \| null | | `data.results[].prices[].promoDetails` | string \| null | | `data.results[].prices[].features` | object | | `data.results[].prices[].features.freeWhoisPrivacy` | boolean | | `data.results[].prices[].features.freeDns` | boolean | | `data.results[].prices[].lastUpdated` | string \| null | | `data.results[].prices[].source` | string | | `data.results[].prices[].sourceName` | string | | `data.results[].prices[].sourceUrl` | string \| null | | `data.results[].prices[].confidence` | string | | `data.results[].prices[].sourceType` | string | | `data.results[].prices[].quoteScope` | string | | `data.results[].prices[].observedAt` | string \| null | | `data.results[].prices[].recommendationEligible` | boolean | | `data.results[].prices[].recommendationExclusionReason` | string \| null | | `data.results[].cheapest` | object | | `data.results[].cheapest.register` | object \| null | | `data.results[].cheapest.renew` | object \| null | | `data.results[].cheapest.transfer` | object \| null | | `data.results[].averagePrice` | object | | `data.results[].averagePrice.register` | number \| null | | `data.results[].averagePrice.renew` | number \| null | | `data.results[].averagePrice.transfer` | number \| null | | `data.results[].priceRange` | object | | `data.results[].priceRange.register` | object \| null | | `data.results[].priceRange.renew` | object \| null | | `data.results[].priceRange.transfer` | object \| null | | `data.results[].lastUpdated` | string \| null | | `data.results[].dataQuality` | object | | `data.results[].dataQuality.sourcesQueried` | integer | | `data.results[].dataQuality.sourcesSucceeded` | integer | | `data.results[].dataQuality.cacheHitRate` | number | | `data.results[].dataQuality.averageConfidence` | string | | `data.results[].price_summary` | object | | `data.results[].price_summary.registrar_count` | integer | | `data.results[].price_summary.registrar_coverage_ratio` | number | | `data.results[].price_summary.price_points` | object | | `data.results[].price_summary.price_points.register` | integer | | `data.results[].price_summary.price_points.renew` | integer | | `data.results[].price_summary.price_points.transfer` | integer | | `data.results[].price_summary.source_counts` | object | | `data.results[].price_summary.confidence_counts` | object | | `data.results[].price_summary.freshness` | object | | `data.results[].price_summary.freshness.freshest_at` | string \| null | | `data.results[].price_summary.freshness.oldest_at` | string \| null | | `data.results[].price_summary.freshness.newest_age_hours` | number \| null | | `data.results[].price_summary.freshness.stale_price_count` | integer | | `data.results[].price_summary.freshness.unknown_freshness_count` | integer | | `data.results[].price_summary.spread` | object | | `data.results[].price_summary.spread.register_usd` | number \| null | | `data.results[].price_summary.spread.renew_usd` | number \| null | | `data.results[].price_summary.spread.transfer_usd` | number \| null | | `data.results[].price_summary.outlier_count` | integer | | `data.results[].price_summary.recommendation_eligible_registrar_count` | integer | | `data.results[].price_summary.quality_status` | string | | `data.results[].price_summary.cheapest_register` | object \| null | | `data.results[].price_summary.cheapest_renew` | object \| null | | `data.results[].price_summary.cheapest_transfer` | object \| null | | `data.results[].checkAccounting` | object | | `data.results[].checkAccounting.plannedChecks` | integer | | `data.results[].checkAccounting.actualChecks` | integer | | `data.results[].checkAccounting.successfulRows` | integer | | `data.results[].checkAccounting.creditsCharged` | integer | | `data.results[].checkAccounting.creditsPerCheck` | integer | | `data.results[].checkAccounting.liveQuoteChecks` | integer | | `data.results[].checkAccounting.creditsPerLiveQuote` | integer | | `data.results[].checkAccounting.creditsRefunded` | integer | | `data.results[].checkAccounting.selectedRegistrars[]` | string[] | | `data.summary` | object | | `data.summary.tldsRequested` | integer | | `data.summary.tldsWithData` | integer | | `data.summary.totalPricePoints` | integer | | `data.summary.quoteCount` | integer | | `data.summary.numericPriceFieldCount` | integer | | `data.summary.market_summary` | object | | `data.summary.market_summary.tlds_requested` | integer | | `data.summary.market_summary.tlds_with_data` | integer | | `data.summary.market_summary.quote_count` | integer | | `data.summary.market_summary.integrated_source_count` | integer | | `data.summary.market_summary.total_price_points` | integer | | `data.summary.market_summary.average_registrar_coverage_ratio` | number | | `data.summary.market_summary.stale_tld_count` | integer | | `data.summary.market_summary.fallback_tld_count` | integer | | `data.summary.market_summary.outlier_tld_count` | integer | | `data.summary.market_summary.widest_register_spread_tld` | string \| null | | `data.summary.market_summary.max_register_spread_usd` | number \| null | | `data.summary.market_summary.freshest_price_at` | string \| null | | `data.summary.market_summary.oldest_price_at` | string \| null | | `data.summary.market_summary.checkAccounting` | object | | `data.summary.market_summary.checkAccounting.plannedChecks` | integer | | `data.summary.market_summary.checkAccounting.actualChecks` | integer | | `data.summary.market_summary.checkAccounting.successfulRows` | integer | | `data.summary.market_summary.checkAccounting.creditsCharged` | integer | | `data.summary.market_summary.checkAccounting.creditsPerCheck` | integer | | `data.summary.market_summary.checkAccounting.liveQuoteChecks` | integer | | `data.summary.market_summary.checkAccounting.creditsPerLiveQuote` | integer | | `data.summary.market_summary.checkAccounting.creditsRefunded` | integer | | `data.summary.market_summary.checkAccounting.selectedRegistrars[]` | string[] | | `data.summary.checkAccounting` | object | | `data.summary.checkAccounting.plannedChecks` | integer | | `data.summary.checkAccounting.actualChecks` | integer | | `data.summary.checkAccounting.successfulRows` | integer | | `data.summary.checkAccounting.creditsCharged` | integer | | `data.summary.checkAccounting.creditsPerCheck` | integer | | `data.summary.checkAccounting.liveQuoteChecks` | integer | | `data.summary.checkAccounting.creditsPerLiveQuote` | integer | | `data.summary.checkAccounting.creditsRefunded` | integer | | `data.summary.checkAccounting.selectedRegistrars[]` | string[] | | `meta` | object | | `meta.requestId` | string | | `meta.servedBy` | string | | `meta.durationMs` | integer | | `meta.cacheStatus` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/prices?tlds=com%2Cnet%2Corg®istrars=porkbun%2Cdynadot&skip_cache=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/prices?tlds=com%2Cnet%2Corg®istrars=porkbun%2Cdynadot&skip_cache=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/prices?tlds=com%2Cnet%2Corg®istrars=porkbun%2Cdynadot&skip_cache=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/prices?tlds=com%2Cnet%2Corg®istrars=porkbun%2Cdynadot&skip_cache=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/prices?tlds=com%2Cnet%2Corg®istrars=porkbun%2Cdynadot&skip_cache=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "results": [ { "tld": "com", "prices": [ { "registrar": "namecheap", "registrarName": "Namecheap", "register": 6.98, "renew": 17.98, "transfer": 9.16, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Namecheap users.getPricing API", "sourceUrl": "https://www.namecheap.com/support/api/methods/users/get-pricing/", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null }, { "registrar": "porkbun", "registrarName": "Porkbun", "register": 11.08, "renew": 11.08, "transfer": 10.74, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Porkbun public pricing API", "sourceUrl": "https://porkbun.com/api/json/v3/documentation", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null } ], "cheapest": { "register": { "registrar": "namecheap", "price": 6.98 }, "renew": { "registrar": "porkbun", "price": 11.08 }, "transfer": { "registrar": "namecheap", "price": 9.16 } }, "averagePrice": { "register": 9.03, "renew": 14.53, "transfer": 9.95 }, "priceRange": { "register": { "min": 6.98, "max": 11.08 }, "renew": { "min": 11.08, "max": 17.98 }, "transfer": { "min": 9.16, "max": 10.74 } }, "lastUpdated": "2026-10-09T18:00:00.000Z", "dataQuality": { "sourcesQueried": 3, "sourcesSucceeded": 3, "cacheHitRate": 1, "averageConfidence": "high" }, "price_summary": { "registrar_count": 2, "registrar_coverage_ratio": 0.02, "price_points": { "register": 2, "renew": 2, "transfer": 2 }, "source_counts": { "api": 2, "cached": 0, "fallback": 0 }, "confidence_counts": { "high": 2, "medium": 0, "low": 0 }, "freshness": { "freshest_at": "2026-10-09T18:00:00.000Z", "oldest_at": "2026-10-09T18:00:00.000Z", "newest_age_hours": 3.1, "stale_price_count": 0, "unknown_freshness_count": 0 }, "spread": { "register_usd": 4.1, "renew_usd": 6.9, "transfer_usd": 1.58 }, "outlier_count": 0, "cheapest_register": { "registrar": "namecheap", "price": 6.98 }, "cheapest_renew": { "registrar": "porkbun", "price": 11.08 }, "cheapest_transfer": { "registrar": "namecheap", "price": 9.16 }, "recommendation_eligible_registrar_count": 2, "quality_status": "healthy" }, "checkAccounting": { "plannedChecks": 4, "actualChecks": 4, "successfulRows": 4, "creditsCharged": 4, "creditsPerCheck": 1, "selectedRegistrars": [ "porkbun", "namecheap" ] } }, { "tld": "org", "prices": [ { "registrar": "porkbun", "registrarName": "Porkbun", "register": 7.99, "renew": 12.37, "transfer": 12.37, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Porkbun public pricing API", "sourceUrl": "https://porkbun.com/api/json/v3/documentation", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null }, { "registrar": "namecheap", "registrarName": "Namecheap", "register": 8.88, "renew": 15.98, "transfer": 11.98, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Namecheap users.getPricing API", "sourceUrl": "https://www.namecheap.com/support/api/methods/users/get-pricing/", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null } ], "cheapest": { "register": { "registrar": "porkbun", "price": 7.99 }, "renew": { "registrar": "porkbun", "price": 12.37 }, "transfer": { "registrar": "namecheap", "price": 11.98 } }, "averagePrice": { "register": 8.44, "renew": 14.18, "transfer": 12.18 }, "priceRange": { "register": { "min": 7.99, "max": 8.88 }, "renew": { "min": 12.37, "max": 15.98 }, "transfer": { "min": 11.98, "max": 12.37 } }, "lastUpdated": "2026-10-09T18:00:00.000Z", "dataQuality": { "sourcesQueried": 3, "sourcesSucceeded": 3, "cacheHitRate": 1, "averageConfidence": "high" }, "price_summary": { "registrar_count": 2, "registrar_coverage_ratio": 0.02, "price_points": { "register": 2, "renew": 2, "transfer": 2 }, "source_counts": { "api": 2, "cached": 0, "fallback": 0 }, "confidence_counts": { "high": 2, "medium": 0, "low": 0 }, "freshness": { "freshest_at": "2026-10-09T18:00:00.000Z", "oldest_at": "2026-10-09T18:00:00.000Z", "newest_age_hours": 3.1, "stale_price_count": 0, "unknown_freshness_count": 0 }, "spread": { "register_usd": 0.89, "renew_usd": 3.61, "transfer_usd": 0.39 }, "outlier_count": 0, "cheapest_register": { "registrar": "porkbun", "price": 7.99 }, "cheapest_renew": { "registrar": "porkbun", "price": 12.37 }, "cheapest_transfer": { "registrar": "namecheap", "price": 11.98 }, "recommendation_eligible_registrar_count": 2, "quality_status": "healthy" }, "checkAccounting": { "plannedChecks": 4, "actualChecks": 4, "successfulRows": 4, "creditsCharged": 4, "creditsPerCheck": 1, "selectedRegistrars": [ "porkbun", "namecheap" ] } } ], "summary": { "tldsRequested": 2, "tldsWithData": 2, "totalPricePoints": 4, "quoteCount": 4, "numericPriceFieldCount": 12, "market_summary": { "tlds_requested": 2, "tlds_with_data": 2, "quote_count": 4, "integrated_source_count": 2, "total_price_points": 12, "average_registrar_coverage_ratio": 0.02, "stale_tld_count": 0, "fallback_tld_count": 0, "outlier_tld_count": 0, "widest_register_spread_tld": "com", "max_register_spread_usd": 4.1, "freshest_price_at": "2026-10-09T18:00:00.000Z", "oldest_price_at": "2026-10-09T18:00:00.000Z", "checkAccounting": { "plannedChecks": 4, "actualChecks": 4, "successfulRows": 4, "creditsCharged": 4, "creditsPerCheck": 1, "selectedRegistrars": [ "porkbun", "namecheap" ] } }, "checkAccounting": { "plannedChecks": 4, "actualChecks": 4, "successfulRows": 4, "creditsCharged": 4, "creditsPerCheck": 1, "selectedRegistrars": [ "porkbun", "namecheap" ] } } }, "meta": { "requestId": "req_8f3k2m1x", "servedBy": "pop=MAD", "durationMs": 184, "cacheStatus": "hit" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable ## POST `/v1/prices/bulk` Operation: `bulkPricing` Credits and authentication: 1 Authentication required POST /v1/prices/bulk Credits: 1/pair #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | tlds | string[] | required | | registrars | string[] | optional | | options | object | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.results[]` | object[] | | `data.results[]` | object | | `data.results[].tld` | string | | `data.results[].prices[]` | object[] | | `data.results[].prices[]` | object | | `data.results[].prices[].registrar` | string | | `data.results[].prices[].registrarName` | string | | `data.results[].prices[].register` | number \| null | | `data.results[].prices[].renew` | number \| null | | `data.results[].prices[].transfer` | number \| null | | `data.results[].prices[].currency` | string | | `data.results[].prices[].promoPrice` | number \| null | | `data.results[].prices[].promoDetails` | string \| null | | `data.results[].prices[].features` | object | | `data.results[].prices[].features.freeWhoisPrivacy` | boolean | | `data.results[].prices[].features.freeDns` | boolean | | `data.results[].prices[].lastUpdated` | string \| null | | `data.results[].prices[].source` | string | | `data.results[].prices[].sourceName` | string | | `data.results[].prices[].sourceUrl` | string \| null | | `data.results[].prices[].confidence` | string | | `data.results[].prices[].sourceType` | string | | `data.results[].prices[].quoteScope` | string | | `data.results[].prices[].observedAt` | string \| null | | `data.results[].prices[].recommendationEligible` | boolean | | `data.results[].prices[].recommendationExclusionReason` | string \| null | | `data.results[].cheapest` | object | | `data.results[].cheapest.register` | object \| null | | `data.results[].cheapest.renew` | object \| null | | `data.results[].cheapest.transfer` | object \| null | | `data.results[].averagePrice` | object | | `data.results[].averagePrice.register` | number \| null | | `data.results[].averagePrice.renew` | number \| null | | `data.results[].averagePrice.transfer` | number \| null | | `data.results[].priceRange` | object | | `data.results[].priceRange.register` | object \| null | | `data.results[].priceRange.renew` | object \| null | | `data.results[].priceRange.transfer` | object \| null | | `data.results[].lastUpdated` | string \| null | | `data.results[].dataQuality` | object | | `data.results[].dataQuality.sourcesQueried` | integer | | `data.results[].dataQuality.sourcesSucceeded` | integer | | `data.results[].dataQuality.cacheHitRate` | number | | `data.results[].dataQuality.averageConfidence` | string | | `data.results[].price_summary` | object | | `data.results[].price_summary.registrar_count` | integer | | `data.results[].price_summary.registrar_coverage_ratio` | number | | `data.results[].price_summary.price_points` | object | | `data.results[].price_summary.price_points.register` | integer | | `data.results[].price_summary.price_points.renew` | integer | | `data.results[].price_summary.price_points.transfer` | integer | | `data.results[].price_summary.source_counts` | object | | `data.results[].price_summary.confidence_counts` | object | | `data.results[].price_summary.freshness` | object | | `data.results[].price_summary.freshness.freshest_at` | string \| null | | `data.results[].price_summary.freshness.oldest_at` | string \| null | | `data.results[].price_summary.freshness.newest_age_hours` | number \| null | | `data.results[].price_summary.freshness.stale_price_count` | integer | | `data.results[].price_summary.freshness.unknown_freshness_count` | integer | | `data.results[].price_summary.spread` | object | | `data.results[].price_summary.spread.register_usd` | number \| null | | `data.results[].price_summary.spread.renew_usd` | number \| null | | `data.results[].price_summary.spread.transfer_usd` | number \| null | | `data.results[].price_summary.outlier_count` | integer | | `data.results[].price_summary.recommendation_eligible_registrar_count` | integer | | `data.results[].price_summary.quality_status` | string | | `data.results[].price_summary.cheapest_register` | object \| null | | `data.results[].price_summary.cheapest_renew` | object \| null | | `data.results[].price_summary.cheapest_transfer` | object \| null | | `data.results[].checkAccounting` | object | | `data.results[].checkAccounting.plannedChecks` | integer | | `data.results[].checkAccounting.actualChecks` | integer | | `data.results[].checkAccounting.successfulRows` | integer | | `data.results[].checkAccounting.creditsCharged` | integer | | `data.results[].checkAccounting.creditsPerCheck` | integer | | `data.results[].checkAccounting.liveQuoteChecks` | integer | | `data.results[].checkAccounting.creditsPerLiveQuote` | integer | | `data.results[].checkAccounting.creditsRefunded` | integer | | `data.results[].checkAccounting.selectedRegistrars[]` | string[] | | `data.summary` | object | | `data.summary.tlds_requested` | integer | | `data.summary.tlds_with_data` | integer | | `data.summary.quote_count` | integer | | `data.summary.integrated_source_count` | integer | | `data.summary.total_price_points` | integer | | `data.summary.average_registrar_coverage_ratio` | number | | `data.summary.stale_tld_count` | integer | | `data.summary.fallback_tld_count` | integer | | `data.summary.outlier_tld_count` | integer | | `data.summary.widest_register_spread_tld` | string \| null | | `data.summary.max_register_spread_usd` | number \| null | | `data.summary.freshest_price_at` | string \| null | | `data.summary.oldest_price_at` | string \| null | | `data.summary.checkAccounting` | object | | `data.summary.checkAccounting.plannedChecks` | integer | | `data.summary.checkAccounting.actualChecks` | integer | | `data.summary.checkAccounting.successfulRows` | integer | | `data.summary.checkAccounting.creditsCharged` | integer | | `data.summary.checkAccounting.creditsPerCheck` | integer | | `data.summary.checkAccounting.liveQuoteChecks` | integer | | `data.summary.checkAccounting.creditsPerLiveQuote` | integer | | `data.summary.checkAccounting.creditsRefunded` | integer | | `data.summary.checkAccounting.selectedRegistrars[]` | string[] | | `data.meta` | object | | `meta` | object | | `meta.requestId` | string | | `meta.servedBy` | string | | `meta.durationMs` | integer | | `meta.cacheStatus` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/prices/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "tlds": [ "com", "net", "org" ], "registrars": [ "porkbun", "dynadot" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/prices/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "tlds": [ "com", "net", "org" ], "registrars": [ "porkbun", "dynadot" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/prices/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "tlds": [ "com", "net", "org", ], "registrars": [ "porkbun", "dynadot", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "tlds": [ "com", "net", "org" ], "registrars": [ "porkbun", "dynadot" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/prices/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/prices/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "tlds" => [ "com", "net", "org" ], "registrars" => [ "porkbun", "dynadot" ] }) #### Example response ```json { "success": true, "data": { "results": [ { "tld": "com", "prices": [ { "registrar": "example", "registrarName": "example", "register": 0.5, "renew": 0.5, "transfer": 0.5, "currency": "USD", "promoPrice": 0.5, "promoDetails": "example", "features": { "freeWhoisPrivacy": false, "freeDns": false }, "lastUpdated": "2026-08-27T12:00:00Z", "source": "api", "sourceName": "example", "sourceUrl": "https://example.com", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-08-27T12:00:00Z", "recommendationEligible": false, "recommendationExclusionReason": "stale" } ], "cheapest": { "register": {}, "renew": {}, "transfer": {} }, "averagePrice": { "register": 0.5, "renew": 0.5, "transfer": 0.5 }, "priceRange": { "register": {}, "renew": {}, "transfer": {} }, "lastUpdated": "2026-08-27T12:00:00Z", "dataQuality": { "sourcesQueried": 1, "sourcesSucceeded": 1, "cacheHitRate": 0.5, "averageConfidence": "high" }, "price_summary": { "registrar_count": 1, "registrar_coverage_ratio": 0.5, "price_points": { "register": 1, "renew": 1, "transfer": 1 }, "source_counts": {}, "confidence_counts": {}, "freshness": { "freshest_at": "2026-08-27T12:00:00Z", "oldest_at": "2026-08-27T12:00:00Z", "newest_age_hours": 0.5, "stale_price_count": 1, "unknown_freshness_count": 1 }, "spread": { "register_usd": 0.5, "renew_usd": 0.5, "transfer_usd": 0.5 }, "outlier_count": 1, "recommendation_eligible_registrar_count": 1, "quality_status": "healthy", "cheapest_register": {}, "cheapest_renew": {}, "cheapest_transfer": {} }, "checkAccounting": { "plannedChecks": 1, "actualChecks": 1, "successfulRows": 1, "creditsCharged": 1, "creditsPerCheck": 1, "selectedRegistrars": [ "example" ], "liveQuoteChecks": 1, "creditsPerLiveQuote": 1, "creditsRefunded": 1 } } ], "summary": { "tlds_requested": 1, "tlds_with_data": 1, "quote_count": 1, "integrated_source_count": 1, "total_price_points": 1, "average_registrar_coverage_ratio": 0.5, "stale_tld_count": 1, "fallback_tld_count": 1, "outlier_tld_count": 1, "widest_register_spread_tld": "com", "max_register_spread_usd": 0.5, "freshest_price_at": "2026-08-27T12:00:00Z", "oldest_price_at": "2026-08-27T12:00:00Z", "checkAccounting": { "plannedChecks": 1, "actualChecks": 1, "successfulRows": 1, "creditsCharged": 1, "creditsPerCheck": 1, "selectedRegistrars": [ "example" ], "liveQuoteChecks": 1, "creditsPerLiveQuote": 1, "creditsRefunded": 1 } }, "meta": {} }, "meta": { "requestId": "request-id", "servedBy": "example", "durationMs": 1, "cacheStatus": "hit" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests - `503` Service Unavailable ## GET `/v1/prices/tld/:tld` Operation: `getTldPricing` Credits and authentication: 1 Authentication required GET /v1/prices/tld/:tld Credits: 1/pair #### Query parameters | Parameter | Type | required | | --- | --- | --- | | tld | string | required | | registrars | string | optional | | skip_cache | boolean Default `false` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.tld` | string | | `data.prices[]` | object[] | | `data.prices[]` | object | | `data.prices[].registrar` | string | | `data.prices[].registrarName` | string | | `data.prices[].register` | number \| null | | `data.prices[].renew` | number \| null | | `data.prices[].transfer` | number \| null | | `data.prices[].currency` | string | | `data.prices[].promoPrice` | number \| null | | `data.prices[].promoDetails` | string \| null | | `data.prices[].features` | object | | `data.prices[].features.freeWhoisPrivacy` | boolean | | `data.prices[].features.freeDns` | boolean | | `data.prices[].lastUpdated` | string \| null | | `data.prices[].source` | string | | `data.prices[].sourceName` | string | | `data.prices[].sourceUrl` | string \| null | | `data.prices[].confidence` | string | | `data.prices[].sourceType` | string | | `data.prices[].quoteScope` | string | | `data.prices[].observedAt` | string \| null | | `data.prices[].recommendationEligible` | boolean | | `data.prices[].recommendationExclusionReason` | string \| null | | `data.cheapest` | object | | `data.cheapest.register` | object \| null | | `data.cheapest.renew` | object \| null | | `data.cheapest.transfer` | object \| null | | `data.averagePrice` | object | | `data.averagePrice.register` | number \| null | | `data.averagePrice.renew` | number \| null | | `data.averagePrice.transfer` | number \| null | | `data.priceRange` | object | | `data.priceRange.register` | object \| null | | `data.priceRange.renew` | object \| null | | `data.priceRange.transfer` | object \| null | | `data.lastUpdated` | string \| null | | `data.dataQuality` | object | | `data.dataQuality.sourcesQueried` | integer | | `data.dataQuality.sourcesSucceeded` | integer | | `data.dataQuality.cacheHitRate` | number | | `data.dataQuality.averageConfidence` | string | | `data.price_summary` | object | | `data.price_summary.registrar_count` | integer | | `data.price_summary.registrar_coverage_ratio` | number | | `data.price_summary.price_points` | object | | `data.price_summary.price_points.register` | integer | | `data.price_summary.price_points.renew` | integer | | `data.price_summary.price_points.transfer` | integer | | `data.price_summary.source_counts` | object | | `data.price_summary.confidence_counts` | object | | `data.price_summary.freshness` | object | | `data.price_summary.freshness.freshest_at` | string \| null | | `data.price_summary.freshness.oldest_at` | string \| null | | `data.price_summary.freshness.newest_age_hours` | number \| null | | `data.price_summary.freshness.stale_price_count` | integer | | `data.price_summary.freshness.unknown_freshness_count` | integer | | `data.price_summary.spread` | object | | `data.price_summary.spread.register_usd` | number \| null | | `data.price_summary.spread.renew_usd` | number \| null | | `data.price_summary.spread.transfer_usd` | number \| null | | `data.price_summary.outlier_count` | integer | | `data.price_summary.recommendation_eligible_registrar_count` | integer | | `data.price_summary.quality_status` | string | | `data.price_summary.cheapest_register` | object \| null | | `data.price_summary.cheapest_renew` | object \| null | | `data.price_summary.cheapest_transfer` | object \| null | | `data.checkAccounting` | object | | `data.checkAccounting.plannedChecks` | integer | | `data.checkAccounting.actualChecks` | integer | | `data.checkAccounting.successfulRows` | integer | | `data.checkAccounting.creditsCharged` | integer | | `data.checkAccounting.creditsPerCheck` | integer | | `data.checkAccounting.liveQuoteChecks` | integer | | `data.checkAccounting.creditsPerLiveQuote` | integer | | `data.checkAccounting.creditsRefunded` | integer | | `data.checkAccounting.selectedRegistrars[]` | string[] | | `meta` | object | | `meta.requestId` | string | | `meta.servedBy` | string | | `meta.durationMs` | integer | | `meta.cacheStatus` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/prices/tld/com?registrars=porkbun%2Cdynadot&skip_cache=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/prices/tld/com?registrars=porkbun%2Cdynadot&skip_cache=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/prices/tld/com?registrars=porkbun%2Cdynadot&skip_cache=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/prices/tld/com?registrars=porkbun%2Cdynadot&skip_cache=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/prices/tld/com?registrars=porkbun%2Cdynadot&skip_cache=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "tld": "com", "prices": [ { "registrar": "example", "registrarName": "example", "register": 0.5, "renew": 0.5, "transfer": 0.5, "currency": "USD", "promoPrice": 0.5, "promoDetails": "example", "features": { "freeWhoisPrivacy": false, "freeDns": false }, "lastUpdated": "2026-08-27T12:00:00Z", "source": "api", "sourceName": "example", "sourceUrl": "https://example.com", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-08-27T12:00:00Z", "recommendationEligible": false, "recommendationExclusionReason": "stale" } ], "cheapest": { "register": {}, "renew": {}, "transfer": {} }, "averagePrice": { "register": 0.5, "renew": 0.5, "transfer": 0.5 }, "priceRange": { "register": {}, "renew": {}, "transfer": {} }, "lastUpdated": "2026-08-27T12:00:00Z", "dataQuality": { "sourcesQueried": 1, "sourcesSucceeded": 1, "cacheHitRate": 0.5, "averageConfidence": "high" }, "price_summary": { "registrar_count": 1, "registrar_coverage_ratio": 0.5, "price_points": { "register": 1, "renew": 1, "transfer": 1 }, "source_counts": {}, "confidence_counts": {}, "freshness": { "freshest_at": "2026-08-27T12:00:00Z", "oldest_at": "2026-08-27T12:00:00Z", "newest_age_hours": 0.5, "stale_price_count": 1, "unknown_freshness_count": 1 }, "spread": { "register_usd": 0.5, "renew_usd": 0.5, "transfer_usd": 0.5 }, "outlier_count": 1, "recommendation_eligible_registrar_count": 1, "quality_status": "healthy", "cheapest_register": {}, "cheapest_renew": {}, "cheapest_transfer": {} }, "checkAccounting": { "plannedChecks": 1, "actualChecks": 1, "successfulRows": 1, "creditsCharged": 1, "creditsPerCheck": 1, "selectedRegistrars": [ "example" ], "liveQuoteChecks": 1, "creditsPerLiveQuote": 1, "creditsRefunded": 1 } }, "meta": { "requestId": "request-id", "servedBy": "example", "durationMs": 1, "cacheStatus": "hit" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable ## GET `/v1/prices/registrars` Operation: `getRegistrars` Credits and authentication: Free Authentication required GET /v1/prices/registrars Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.registrars[]` | object[] | | `data.registrars[]` | object | | `data.registrars[].id` | string | | `data.registrars[].name` | string | | `data.registrars[].website` | string | | `data.registrars[].apiAvailable` | boolean | | `data.registrars[].providerType` | string | | `data.registrars[].pricingIntegrated` | boolean | | `data.registrars[].pricingIntegration` | string \| null | | `data.registrars[].standardPricingIntegration` | string \| null | | `data.registrars[].exactDomainPricingIntegrated` | boolean | | `data.registrars[].pricingModes[]` | string[] | | `data.registrars[].features` | object | | `data.registrars[].features.freeWhoisPrivacy` | boolean | | `data.registrars[].features.freeDns` | boolean | | `data.registrars[].features.bulkDiscounts` | boolean | | `data.pricingCoverage` | object | | `data.pricingCoverage.listedRegistrarCount` | integer | | `data.pricingCoverage.integratedRegistrarCount` | integer | | `data.pricingCoverage.standardPricingSources[]` | string[] | | `data.pricingCoverage.directPricingSources[]` | string[] | | `data.pricingCoverage.scrapedPricingSources[]` | string[] | | `data.pricingCoverage.exactDomainPricingSources[]` | string[] | | `data.pricingCoverage.snapshotGeneratedAt` | string \| null | | `data.pricingCoverage.sourceHealth[]` | object[] | | `data.pricingCoverage.sourceHealth[]` | object | | `data.pricingCoverage.sourceHealth[].source` | string | | `data.pricingCoverage.sourceHealth[].registrar` | string \| null | | `data.pricingCoverage.sourceHealth[].configured` | boolean | | `data.pricingCoverage.sourceHealth[].success` | boolean | | `data.pricingCoverage.sourceHealth[].sourceType` | string \| null | | `data.pricingCoverage.sourceHealth[].tldCount` | integer | | `data.pricingCoverage.sourceHealth[].durationMs` | integer | | `data.pricingCoverage.sourceHealth[].error` | string \| null | | `data.pricingCoverage.sourceHealth[].retainedPreviousSnapshot` | boolean | | `data.pricingCoverage.sourceHealth[].runId` | string | | `data.pricingCoverage.sourceHealth[].fetchedAt` | string | | `data.pricingCoverage.sourceHealth[].previousTldCount` | integer \| null | | `data.pricingCoverage.sourceHealth[].lastSuccessAt` | string \| null | | `data.pricingCoverage.sourceHealth[].contentHash` | string \| null | | `data.pricingCoverage.sourceHealth[].schemaFingerprint` | string \| null | | `data.pricingCoverage.sourceHealth[].fieldCoverage` | object | | `data.pricingCoverage.sourceHealth[].fieldCoverage.register` | integer | | `data.pricingCoverage.sourceHealth[].fieldCoverage.renew` | integer | | `data.pricingCoverage.sourceHealth[].fieldCoverage.transfer` | integer | | `data.pricingCoverage.note` | string | | `data.lastUpdated` | string | | `meta` | object | | `meta.requestId` | string | | `meta.servedBy` | string | | `meta.durationMs` | integer | | `meta.cacheStatus` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/prices/registrars" ``` ```javascript const response = await fetch("https://domscan.net/v1/prices/registrars", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/prices/registrars", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/prices/registrars", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/prices/registrars") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "registrars": [ { "id": "porkbun", "name": "Porkbun", "website": "https://porkbun.com", "apiAvailable": true, "providerType": "registrar", "pricingIntegrated": true, "pricingIntegration": "official_api", "standardPricingIntegration": "official_api", "exactDomainPricingIntegrated": false, "pricingModes": [ "tld_standard" ], "features": { "freeWhoisPrivacy": true, "freeDns": true, "bulkDiscounts": false } } ], "pricingCoverage": { "listedRegistrarCount": 120, "integratedRegistrarCount": 29, "standardPricingSources": [ "porkbun", "dynadot", "namesilo" ], "directPricingSources": [ "porkbun", "namesilo", "namebright" ], "scrapedPricingSources": [ "dynadot", "gandi", "name_com" ], "exactDomainPricingSources": [ "cloudflare", "namesilo", "name_com", "spaceship", "vercel", "openprovider" ], "snapshotGeneratedAt": "2026-07-12T10:35:11.735Z", "sourceHealth": [ { "source": "porkbun", "registrar": "porkbun", "configured": true, "success": true, "sourceType": "official_api", "tldCount": 907, "durationMs": 421, "error": null, "retainedPreviousSnapshot": false } ], "note": "Registrar entries are metadata. Standard and exact-domain integrations are reported separately." }, "lastUpdated": "2026-07-12T10:35:11.735Z" }, "meta": { "requestId": "req_example", "servedBy": "pop=MAD", "durationMs": 12, "cacheStatus": "bypass" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## GET `/v1/prices/compare` Operation: `comparePrices` Credits and authentication: 1 Authentication required GET /v1/prices/compare Credits: 1/pair #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | registrars | string | optional | | skip_cache | boolean Default `false` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.tld` | string | | `data.pricing` | object | | `data.pricing.tld` | string | | `data.pricing.prices[]` | object[] | | `data.pricing.prices[]` | object | | `data.pricing.prices[].registrar` | string | | `data.pricing.prices[].registrarName` | string | | `data.pricing.prices[].register` | number \| null | | `data.pricing.prices[].renew` | number \| null | | `data.pricing.prices[].transfer` | number \| null | | `data.pricing.prices[].currency` | string | | `data.pricing.prices[].promoPrice` | number \| null | | `data.pricing.prices[].promoDetails` | string \| null | | `data.pricing.prices[].features` | object | | `data.pricing.prices[].features.freeWhoisPrivacy` | boolean | | `data.pricing.prices[].features.freeDns` | boolean | | `data.pricing.prices[].lastUpdated` | string \| null | | `data.pricing.prices[].source` | string | | `data.pricing.prices[].sourceName` | string | | `data.pricing.prices[].sourceUrl` | string \| null | | `data.pricing.prices[].confidence` | string | | `data.pricing.prices[].sourceType` | string | | `data.pricing.prices[].quoteScope` | string | | `data.pricing.prices[].observedAt` | string \| null | | `data.pricing.prices[].recommendationEligible` | boolean | | `data.pricing.prices[].recommendationExclusionReason` | string \| null | | `data.pricing.cheapest` | object | | `data.pricing.cheapest.register` | object \| null | | `data.pricing.cheapest.renew` | object \| null | | `data.pricing.cheapest.transfer` | object \| null | | `data.pricing.averagePrice` | object | | `data.pricing.averagePrice.register` | number \| null | | `data.pricing.averagePrice.renew` | number \| null | | `data.pricing.averagePrice.transfer` | number \| null | | `data.pricing.priceRange` | object | | `data.pricing.priceRange.register` | object \| null | | `data.pricing.priceRange.renew` | object \| null | | `data.pricing.priceRange.transfer` | object \| null | | `data.pricing.lastUpdated` | string \| null | | `data.pricing.dataQuality` | object | | `data.pricing.dataQuality.sourcesQueried` | integer | | `data.pricing.dataQuality.sourcesSucceeded` | integer | | `data.pricing.dataQuality.cacheHitRate` | number | | `data.pricing.dataQuality.averageConfidence` | string | | `data.pricing.price_summary` | object | | `data.pricing.price_summary.registrar_count` | integer | | `data.pricing.price_summary.registrar_coverage_ratio` | number | | `data.pricing.price_summary.price_points` | object | | `data.pricing.price_summary.price_points.register` | integer | | `data.pricing.price_summary.price_points.renew` | integer | | `data.pricing.price_summary.price_points.transfer` | integer | | `data.pricing.price_summary.source_counts` | object | | `data.pricing.price_summary.confidence_counts` | object | | `data.pricing.price_summary.freshness` | object | | `data.pricing.price_summary.freshness.freshest_at` | string \| null | | `data.pricing.price_summary.freshness.oldest_at` | string \| null | | `data.pricing.price_summary.freshness.newest_age_hours` | number \| null | | `data.pricing.price_summary.freshness.stale_price_count` | integer | | `data.pricing.price_summary.freshness.unknown_freshness_count` | integer | | `data.pricing.price_summary.spread` | object | | `data.pricing.price_summary.spread.register_usd` | number \| null | | `data.pricing.price_summary.spread.renew_usd` | number \| null | | `data.pricing.price_summary.spread.transfer_usd` | number \| null | | `data.pricing.price_summary.outlier_count` | integer | | `data.pricing.price_summary.recommendation_eligible_registrar_count` | integer | | `data.pricing.price_summary.quality_status` | string | | `data.pricing.price_summary.cheapest_register` | object \| null | | `data.pricing.price_summary.cheapest_renew` | object \| null | | `data.pricing.price_summary.cheapest_transfer` | object \| null | | `data.pricing.checkAccounting` | object | | `data.pricing.checkAccounting.plannedChecks` | integer | | `data.pricing.checkAccounting.actualChecks` | integer | | `data.pricing.checkAccounting.successfulRows` | integer | | `data.pricing.checkAccounting.creditsCharged` | integer | | `data.pricing.checkAccounting.creditsPerCheck` | integer | | `data.pricing.checkAccounting.liveQuoteChecks` | integer | | `data.pricing.checkAccounting.creditsPerLiveQuote` | integer | | `data.pricing.checkAccounting.creditsRefunded` | integer | | `data.pricing.checkAccounting.selectedRegistrars[]` | string[] | | `data.recommendation` | object | | `data.recommendation.registrar` | string | | `data.recommendation.reason` | string | | `data.recommendation.savings` | number | | `data.recommendation_status` | string | | `data.cloudflare` | object | | `data.cloudflare.source` | string | | `data.cloudflare.checked` | boolean | | `data.cloudflare.status` | string | | `data.cloudflare.supported` | boolean \| null | | `data.cloudflare.registrable` | boolean \| null | | `data.cloudflare.reason` | string \| null | | `data.cloudflare.pricing` | object | | `data.cloudflare.pricing.currency` | string \| null | | `data.cloudflare.pricing.registrationCost` | number \| null | | `data.cloudflare.pricing.renewalCost` | number \| null | | `data.cloudflare.checkedAt` | string \| null | | `data.exact_quotes[]` | object[] | | `data.exact_quotes[]` | object | | `data.exact_quotes[].registrar` | string | | `data.exact_quotes[].sourceType` | string | | `data.exact_quotes[].sourceName` | string | | `data.exact_quotes[].sourceUrl` | string | | `data.exact_quotes[].quoteScope` | string | | `data.exact_quotes[].checked` | boolean | | `data.exact_quotes[].configured` | boolean | | `data.exact_quotes[].status` | string | | `data.exact_quotes[].available` | boolean \| null | | `data.exact_quotes[].definitive` | boolean \| null | | `data.exact_quotes[].premium` | boolean \| null | | `data.exact_quotes[].minimumRegistrationYears` | integer \| null | | `data.exact_quotes[].currency` | string \| null | | `data.exact_quotes[].register` | number \| null | | `data.exact_quotes[].renew` | number \| null | | `data.exact_quotes[].transfer` | number \| null | | `data.exact_quotes[].checkedAt` | string \| null | | `data.exact_quotes[].errorCode` | string \| null | | `data.checkAccounting` | object | | `data.checkAccounting.plannedChecks` | integer | | `data.checkAccounting.actualChecks` | integer | | `data.checkAccounting.successfulRows` | integer | | `data.checkAccounting.creditsCharged` | integer | | `data.checkAccounting.creditsPerCheck` | integer | | `data.checkAccounting.liveQuoteChecks` | integer | | `data.checkAccounting.creditsPerLiveQuote` | integer | | `data.checkAccounting.creditsRefunded` | integer | | `data.checkAccounting.selectedRegistrars[]` | string[] | | `data.comparison_summary` | object | | `data.comparison_summary.first_year_registrar` | string \| null | | `data.comparison_summary.renewal_registrar` | string \| null | | `data.comparison_summary.transfer_registrar` | string \| null | | `data.comparison_summary.first_year_price` | number \| null | | `data.comparison_summary.renewal_price` | number \| null | | `data.comparison_summary.transfer_price` | number \| null | | `data.comparison_summary.first_year_vs_renewal_delta_usd` | number \| null | | `data.comparison_summary.first_year_vs_renewal_delta_pct` | number \| null | | `data.comparison_summary.cheapest_register_renews_higher` | boolean | | `data.comparison_summary.renewal_trap_warning` | boolean | | `data.comparison_summary.transfer_savings_usd` | number \| null | | `data.comparison_summary.cloudflare_live_status` | string | | `data.comparison_summary.recommendation_basis` | string | | `meta` | object | | `meta.requestId` | string | | `meta.servedBy` | string | | `meta.durationMs` | integer | | `meta.cacheStatus` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/prices/compare?domain=example.com®istrars=porkbun&skip_cache=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/prices/compare?domain=example.com®istrars=porkbun&skip_cache=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/prices/compare?domain=example.com®istrars=porkbun&skip_cache=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/prices/compare?domain=example.com®istrars=porkbun&skip_cache=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/prices/compare?domain=example.com®istrars=porkbun&skip_cache=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "brandpilot.com", "tld": "com", "pricing": { "tld": "com", "prices": [ { "registrar": "namecheap", "registrarName": "Namecheap", "register": 6.98, "renew": 17.98, "transfer": 9.16, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Namecheap users.getPricing API", "sourceUrl": "https://www.namecheap.com/support/api/methods/users/get-pricing/", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null }, { "registrar": "dynadot", "registrarName": "Dynadot", "register": 10.99, "renew": 11.99, "transfer": 10.49, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Dynadot official pricing", "sourceUrl": "https://www.dynadot.com/domain/prices", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null }, { "registrar": "porkbun", "registrarName": "Porkbun", "register": 11.08, "renew": 11.08, "transfer": 10.74, "currency": "USD", "features": { "freeWhoisPrivacy": true, "freeDns": true }, "lastUpdated": "2026-10-09T18:00:00.000Z", "source": "api", "sourceName": "Porkbun public pricing API", "sourceUrl": "https://porkbun.com/api/json/v3/documentation", "confidence": "high", "sourceType": "official_api", "quoteScope": "tld_standard", "observedAt": "2026-10-09T18:00:00.000Z", "recommendationEligible": true, "recommendationExclusionReason": null } ], "cheapest": { "register": { "registrar": "namecheap", "price": 6.98 }, "renew": { "registrar": "porkbun", "price": 11.08 }, "transfer": { "registrar": "namecheap", "price": 9.16 } }, "averagePrice": { "register": 9.68, "renew": 13.68, "transfer": 10.13 }, "priceRange": { "register": { "min": 6.98, "max": 11.08 }, "renew": { "min": 11.08, "max": 17.98 }, "transfer": { "min": 9.16, "max": 10.74 } }, "lastUpdated": "2026-10-09T18:00:00.000Z", "dataQuality": { "sourcesQueried": 3, "sourcesSucceeded": 3, "cacheHitRate": 1, "averageConfidence": "high" }, "price_summary": { "registrar_count": 3, "registrar_coverage_ratio": 0.03, "price_points": { "register": 3, "renew": 3, "transfer": 3 }, "source_counts": { "api": 3, "cached": 0, "fallback": 0 }, "confidence_counts": { "high": 3, "medium": 0, "low": 0 }, "freshness": { "freshest_at": "2026-10-09T18:00:00.000Z", "oldest_at": "2026-10-09T18:00:00.000Z", "newest_age_hours": 3.1, "stale_price_count": 0, "unknown_freshness_count": 0 }, "spread": { "register_usd": 4.1, "renew_usd": 6.9, "transfer_usd": 1.58 }, "outlier_count": 0, "cheapest_register": { "registrar": "namecheap", "price": 6.98 }, "cheapest_renew": { "registrar": "porkbun", "price": 11.08 }, "cheapest_transfer": { "registrar": "namecheap", "price": 9.16 }, "recommendation_eligible_registrar_count": 3, "quality_status": "healthy" }, "checkAccounting": { "plannedChecks": 4, "actualChecks": 4, "successfulRows": 4, "creditsCharged": 4, "creditsPerCheck": 1, "liveQuoteChecks": 1, "creditsPerLiveQuote": 1, "creditsRefunded": 0, "selectedRegistrars": [ "porkbun", "dynadot", "namecheap", "cloudflare" ] } }, "recommendation": { "registrar": "namecheap", "reason": "Lowest registration price: 6.98 USD", "savings": 4.1 }, "recommendation_status": "available", "cloudflare": { "source": "registrar_api_beta", "checked": true, "status": "registrable", "supported": true, "registrable": true, "reason": null, "pricing": { "currency": "USD", "registrationCost": 10.46, "renewalCost": 10.46 }, "checkedAt": "2026-10-09T18:03:12.000Z" }, "exact_quotes": [ { "registrar": "cloudflare", "sourceType": "official_api", "sourceName": "Cloudflare Registrar domain check API", "sourceUrl": "https://developers.cloudflare.com/registrar/registrar-api/", "quoteScope": "exact_domain", "checked": true, "configured": true, "status": "registrable", "available": true, "definitive": true, "premium": false, "minimumRegistrationYears": null, "currency": "USD", "register": 10.46, "renew": 10.46, "transfer": null, "checkedAt": "2026-10-09T18:03:12.000Z", "errorCode": null } ], "checkAccounting": { "plannedChecks": 4, "actualChecks": 4, "successfulRows": 4, "creditsCharged": 4, "creditsPerCheck": 1, "liveQuoteChecks": 1, "creditsPerLiveQuote": 1, "creditsRefunded": 0, "selectedRegistrars": [ "porkbun", "dynadot", "namecheap", "cloudflare" ] }, "comparison_summary": { "first_year_registrar": "namecheap", "renewal_registrar": "porkbun", "transfer_registrar": "namecheap", "first_year_price": 6.98, "renewal_price": 17.98, "transfer_price": 9.16, "first_year_vs_renewal_delta_usd": 11, "first_year_vs_renewal_delta_pct": 157.59, "cheapest_register_renews_higher": true, "renewal_trap_warning": true, "transfer_savings_usd": -2.18, "cloudflare_live_status": "registrable", "recommendation_basis": "renewal_savings" } }, "meta": { "requestId": "req_5t9p4c7z", "servedBy": "pop=MAD", "durationMs": 1260, "cacheStatus": "hit" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable ## GET `/v1/pricing` Operation: `getPricingInfo` Credits and authentication: Free Authentication optional GET /v1/pricing Credits: 0 #### Response fields | Field | Type | | --- | --- | | `currency` | string | | `signup_bonus` | integer | | `monthly_free_credits` | integer | | `monthly_refresh` | string | | `enforcement` | string | | `bulk_pricing_note` | string | | `endpoints[]` | object[] | | `endpoints[]` | object | | `endpoints[].endpoint` | string | | `endpoints[].method` | string | | `endpoints[].credits` | integer | | `endpoints[].variants[]` | object[] | | `endpoints[].variants[]` | object | | `endpoints[].variants[].parameter` | string | | `endpoints[].variants[].equals` | unknown | | `endpoints[].variants[].credits` | integer | | `endpoints[].bulk_pricing` | object | | `endpoints[].bulk_pricing.per_item_rate` | integer | | `endpoints[].bulk_pricing.formula` | string | | `endpoints[].bulk_pricing.min_cost` | integer | | `endpoints[].pair_rates[]` | integer[] | | `endpoints[].note` | string | | `free_endpoints[]` | string[] | | `note` | string | #### Example request ```bash curl "https://domscan.net/v1/pricing" ``` ```javascript const response = await fetch("https://domscan.net/v1/pricing"); const data = await response.json(); console.log(data); ``` ```python import requests response = requests.get( "https://domscan.net/v1/pricing", ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/pricing", nil) if err != nil { panic(err) } resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/pricing") request = Net::HTTP::Get.new(uri) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "currency": "credits", "signup_bonus": 1, "monthly_free_credits": 1, "monthly_refresh": "example", "enforcement": "example", "bulk_pricing_note": "example", "endpoints": [ { "endpoint": "example", "method": "GET", "credits": 1, "variants": [ { "parameter": "example", "credits": 1 } ], "bulk_pricing": { "per_item_rate": 1, "formula": "example", "min_cost": 1 }, "pair_rates": [ 1 ], "note": "example" } ], "free_endpoints": [ "example" ], "note": "example" } ``` #### HTTP status codes - `200` OK - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-score # Domain Score API Get a comprehensive quality score for a domain based on multiple factors. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-score-api) ## Operations GET `/v1/score` [View API reference](https://domscan.net/docs/products/domain-score#getDomainScore) POST `/v1/score/compare` [View API reference](https://domscan.net/docs/products/domain-score#compareBrandNames) GET `/v1/score/info` [View API reference](https://domscan.net/docs/products/domain-score#getScoreInfo) ## GET `/v1/score` Operation: `getDomainScore` Credits and authentication: 1 Authentication required GET /v1/score Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | name | string | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `name` | string | | `input` | string | | `scored_label` | string | | `tld` | string | | `overall_score` | integer | | `grade` | string | | `scores` | object | | `scores.length` | integer | | `scores.pronounceability` | number | | `scores.memorability` | integer | | `scores.spelling` | integer | | `scores.uniqueness` | integer | | `scores.brandability` | integer | | `score_explanation` | object | | `score_explanation.score_band` | string | | `score_explanation.top_strengths[]` | object[] | | `score_explanation.top_strengths[]` | object | | `score_explanation.top_strengths[].dimension` | string | | `score_explanation.top_strengths[].score` | number | | `score_explanation.top_strengths[].weight` | number | | `score_explanation.top_blockers[]` | object[] | | `score_explanation.top_blockers[]` | object | | `score_explanation.top_blockers[].dimension` | string | | `score_explanation.top_blockers[].score` | number | | `score_explanation.top_blockers[].weight` | number | | `score_explanation.weighted_dimensions` | object | | `score_explanation.most_sensitive_dimension` | string | | `score_explanation.points_to_next_grade` | integer \| null | | `analysis` | object | | `analysis.syllable_count` | integer | | `analysis.character_count` | integer | | `analysis.has_vowels` | boolean | | `analysis.has_numbers` | boolean | | `analysis.has_hyphens` | boolean | | `analysis.is_dictionary_word` | boolean | | `analysis.is_premium_word` | boolean | | `analysis.is_too_generic` | boolean | | `analysis.starts_with_vowel` | boolean | | `analysis.ends_with_vowel` | boolean | | `analysis.has_repeated_letters` | boolean | | `analysis.vowel_ratio` | number | | `recommendations[]` | string[] | | `available_tlds[]` | string[] | | `feedback[]` | string[] | | `meta` | object | | `meta.methodology` | string | | `meta.disclaimer` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/score?name=brandify&domain=brandify.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/score?name=brandify&domain=brandify.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/score?name=brandify&domain=brandify.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/score?name=brandify&domain=brandify.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/score?name=brandify&domain=brandify.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "name": "brandpilot", "input": "brandpilot.io", "scored_label": "brandpilot", "tld": "io", "overall_score": 73, "grade": "B", "scores": { "length": 60, "pronounceability": 68.33, "memorability": 65, "spelling": 80, "uniqueness": 65, "brandability": 95 }, "score_explanation": { "score_band": "strong", "top_strengths": [ { "dimension": "brandability", "score": 95, "weight": 0.2 }, { "dimension": "memorability", "score": 65, "weight": 0.2 }, { "dimension": "pronounceability", "score": 68.33, "weight": 0.18 } ], "top_blockers": [ { "dimension": "length", "score": 60, "weight": 0.12 }, { "dimension": "memorability", "score": 65, "weight": 0.2 }, { "dimension": "uniqueness", "score": 65, "weight": 0.15 } ], "weighted_dimensions": { "length": { "score": 60, "weight": 0.12, "weighted_points": 7 }, "pronounceability": { "score": 68.33, "weight": 0.18, "weighted_points": 12 }, "memorability": { "score": 65, "weight": 0.2, "weighted_points": 13 }, "spelling": { "score": 80, "weight": 0.15, "weighted_points": 12 }, "uniqueness": { "score": 65, "weight": 0.15, "weighted_points": 10 }, "brandability": { "score": 95, "weight": 0.2, "weighted_points": 19 } }, "most_sensitive_dimension": "memorability", "points_to_next_grade": 7 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/score/compare` Operation: `compareBrandNames` Credits and authentication: 2 Authentication required POST /v1/score/compare Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | names | string[] | required | #### Response fields | Field | Type | | --- | --- | | `names[]` | object[] | | `names[]` | object | | `best` | string \| null | | `ranking[]` | object[] | | `ranking[]` | object | | `ranking[].name` | string | | `ranking[].score` | number | | `ranking[].rank` | integer | | `decision_summary` | object | | `decision_summary.compared_count` | integer | | `decision_summary.best` | string \| null | | `decision_summary.runner_up` | string \| null | | `decision_summary.score_margin` | integer \| null | | `decision_summary.score_spread` | integer | | `decision_summary.tie_breaker` | string \| null | | `decision_summary.winning_dimension` | string \| null | | `meta` | object | | `meta.total_compared` | integer | | `meta.valid_scores` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/score/compare" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "names": [ "brandpilot", "launchly", "nimbus" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/score/compare", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "names": [ "brandpilot", "launchly", "nimbus" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/score/compare", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "names": [ "brandpilot", "launchly", "nimbus", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "names": [ "brandpilot", "launchly", "nimbus" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/score/compare", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/score/compare") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "names" => [ "brandpilot", "launchly", "nimbus" ] }) #### Example response ```json { "names": [ { "name": "brandify", "score": 88, "grade": "A", "verdict": "Strong" }, { "name": "brandpilot", "score": 82, "grade": "B+", "verdict": "Promising" } ], "best": "brandify", "ranking": [ { "name": "brandify", "score": 88, "rank": 1 }, { "name": "brandpilot", "score": 82, "rank": 2 } ], "decision_summary": { "compared_count": 2, "best": "brandify", "runner_up": "brandpilot", "score_margin": 6, "score_spread": 6, "tie_breaker": "higher_brandability", "winning_dimension": "brandability" }, "meta": { "total_compared": 2, "valid_scores": 2 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/score/info` Operation: `getScoreInfo` Credits and authentication: Free Authentication required GET /v1/score/info Credits: 0 #### Response fields | Field | Type | | --- | --- | | `scoring_dimensions` | object | | `grade_scale` | object | | `endpoints` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/score/info" ``` ```javascript const response = await fetch("https://domscan.net/v1/score/info", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/score/info", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/score/info", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/score/info") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "scoring_dimensions": { "length": { "weight": 0.12, "description": "Rewards concise names" }, "pronounceability": { "weight": 0.18, "description": "Rewards names that are easy to say" } }, "grade_scale": { "A+": "Exceptional", "A": "Excellent", "B": "Good", "C": "Average", "D": "Weak", "F": "Poor" }, "endpoints": { "GET /v1/score?name=": "Score a single name", "POST /v1/score/compare": "Compare multiple names", "GET /v1/score/info": "Get scoring methodology" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/whois # WHOIS Lookup API Get WHOIS information for a domain including registrar, dates, and status. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/whois-api) ## Operations GET `/v1/whois` [View API reference](https://domscan.net/docs/products/whois#getWhois) GET `/v2/whois` [View API reference](https://domscan.net/docs/products/whois#getWhoisV2) POST `/v1/whois/bulk` [View API reference](https://domscan.net/docs/products/whois#bulkWhois) GET `/v1/whois/history` [View API reference](https://domscan.net/docs/products/whois#getWhoisHistory) ## GET `/v1/whois` Operation: `getWhois` Credits and authentication: 3 Authentication required GET /v1/whois Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `registered` | boolean \| null | | `available` | boolean \| null | | `availability_reason` | string | | `registrar` | string \| null | | `registrar_url` | string \| null | | `registrar_iana_id` | string \| null | | `created_date` | string \| null | | `updated_date` | string \| null | | `expiry_date` | string \| null | | `domain_age_days` | integer \| null | | `domain_age_years` | integer \| null | | `is_newly_registered` | boolean | | `days_until_expiry` | integer \| null | | `transfer_locked` | boolean | | `nameservers[]` | string[] | | `status[]` | string[] | | `dnssec` | boolean | | `contacts` | object | | `contacts.registrant` | object | | `contacts.registrant.name` | string \| null | | `contacts.registrant.organization` | string \| null | | `contacts.registrant.email` | string \| null | | `contacts.registrant.phone` | string \| null | | `contacts.registrant.fax` | string \| null | | `contacts.registrant.address` | object | | `contacts.registrant.address.street` | string \| null | | `contacts.registrant.address.city` | string \| null | | `contacts.registrant.address.state` | string \| null | | `contacts.registrant.address.postal_code` | string \| null | | `contacts.registrant.address.country` | string \| null | | `contacts.registrant.role` | string | | `contacts.admin` | object | | `contacts.admin.name` | string \| null | | `contacts.admin.organization` | string \| null | | `contacts.admin.email` | string \| null | | `contacts.admin.phone` | string \| null | | `contacts.admin.fax` | string \| null | | `contacts.admin.address` | object | | `contacts.admin.address.street` | string \| null | | `contacts.admin.address.city` | string \| null | | `contacts.admin.address.state` | string \| null | | `contacts.admin.address.postal_code` | string \| null | | `contacts.admin.address.country` | string \| null | | `contacts.admin.role` | string | | `contacts.tech` | object | | `contacts.tech.name` | string \| null | | `contacts.tech.organization` | string \| null | | `contacts.tech.email` | string \| null | | `contacts.tech.phone` | string \| null | | `contacts.tech.fax` | string \| null | | `contacts.tech.address` | object | | `contacts.tech.address.street` | string \| null | | `contacts.tech.address.city` | string \| null | | `contacts.tech.address.state` | string \| null | | `contacts.tech.address.postal_code` | string \| null | | `contacts.tech.address.country` | string \| null | | `contacts.tech.role` | string | | `contacts.billing` | object | | `contacts.billing.name` | string \| null | | `contacts.billing.organization` | string \| null | | `contacts.billing.email` | string \| null | | `contacts.billing.phone` | string \| null | | `contacts.billing.fax` | string \| null | | `contacts.billing.address` | object | | `contacts.billing.address.street` | string \| null | | `contacts.billing.address.city` | string \| null | | `contacts.billing.address.state` | string \| null | | `contacts.billing.address.postal_code` | string \| null | | `contacts.billing.address.country` | string \| null | | `contacts.billing.role` | string | | `privacy` | object | | `privacy.is_private` | boolean | | `privacy.privacy_service` | string \| null | | `privacy.detected_patterns[]` | string[] | | `raw_rdap_link` | string \| null | | `raw_whois` | string \| null | | `abuse_contact` | object \| null | | `registry_domain_id` | string \| null | | `registrar_whois_server` | string \| null | | `traditional_contacts` | object | | `nameserver_ips[]` | object[] | | `nameserver_ips[]` | object | | `nameserver_ips[].name` | string | | `nameserver_ips[].ipv4` | string \| null | | `nameserver_ips[].ipv6` | string \| null | | `checked_at` | string | | `query_time_ms` | integer | | `summary` | object | | `edge_summary` | object | | `edge_summary.relay_configured` | boolean | | `edge_summary.data_sources[]` | string[] | | `edge_summary.authoritative_source` | string | | `edge_summary.relay_whois_used` | boolean | | `edge_summary.raw_whois_available` | boolean | | `edge_summary.parse_error_count` | integer \| null | | `edge_summary.registered` | boolean \| null | | `edge_summary.available` | boolean \| null | | `edge_summary.registration_age_days` | integer \| null | | `edge_summary.days_until_expiry` | integer \| null | | `edge_summary.expires_within_30_days` | boolean \| null | | `edge_summary.transfer_locked` | boolean \| null | | `edge_summary.privacy_protected` | boolean \| null | | `edge_summary.dnssec` | boolean \| null | | `edge_summary.nameserver_count` | integer | | `edge_summary.contact_roles_available[]` | string[] | | `edge_summary.abuse_contact_available` | boolean | | `edge_summary.registrar_whois_server` | string \| null | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/whois?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/whois?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/whois?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/whois?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/whois?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "registrar": "Example Registrar, Inc.", "registrar_url": "https://registrar.example.net", "registrar_iana_id": "9999", "created_date": "2019-03-11T14:22:08Z", "updated_date": "2026-03-10T09:41:55Z", "expiry_date": "2027-03-11T14:22:08Z", "domain_age_days": 2769, "domain_age_years": 7, "is_newly_registered": false, "days_until_expiry": 153, "transfer_locked": true, "status": [ "client transfer prohibited" ], "nameservers": [ "ns1.example.net", "ns2.example.net" ], "dnssec": false, "contacts": { "registrant": null, "admin": null, "tech": null, "billing": null }, "privacy": { "is_private": false, "privacy_service": null, "detected_patterns": [] }, "raw_rdap_link": "https://rdap.example.net/domain/example.com", "checked_at": "2026-10-09T10:15:30.000Z", "query_time_ms": 412, "registered": true, "summary": { "has_registrant": false, "has_admin": false, "has_tech": false, "has_billing": false, "contact_count": 0, "is_privacy_protected": false }, "edge_summary": { "relay_configured": true, "data_sources": [ "rdap" ], "authoritative_source": "rdap", "relay_whois_used": false, "raw_whois_available": false, "parse_error_count": null, "registered": true, "available": false, "registration_age_days": 2769, "days_until_expiry": 153, "expires_within_30_days": false, "transfer_locked": true, "privacy_protected": false, "dnssec": false, "nameserver_count": 2, "contact_roles_available": [], "abuse_contact_available": false, "registrar_whois_server": null }, "meta": { "served_by": "pop=MAD country=ES", "data_source": "rdap", "note": "Contact information may be redacted due to privacy regulations (GDPR)" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## GET `/v2/whois` Operation: `getWhoisV2` Credits and authentication: 3 Authentication required GET /v2/whois Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `registered` | boolean \| null | | `available` | boolean \| null | | `availability_reason` | string | | `registrar` | string \| null | | `registrar_url` | string \| null | | `registrar_iana_id` | string \| null | | `created_date` | string \| null | | `updated_date` | string \| null | | `expiry_date` | string \| null | | `domain_age_days` | integer \| null | | `domain_age_years` | integer \| null | | `is_newly_registered` | boolean | | `days_until_expiry` | integer \| null | | `transfer_locked` | boolean | | `nameservers[]` | string[] | | `status[]` | string[] | | `dnssec` | boolean | | `contacts` | object | | `contacts.registrant` | object | | `contacts.registrant.name` | string \| null | | `contacts.registrant.organization` | string \| null | | `contacts.registrant.email` | string \| null | | `contacts.registrant.phone` | string \| null | | `contacts.registrant.fax` | string \| null | | `contacts.registrant.address` | object | | `contacts.registrant.address.street` | string \| null | | `contacts.registrant.address.city` | string \| null | | `contacts.registrant.address.state` | string \| null | | `contacts.registrant.address.postal_code` | string \| null | | `contacts.registrant.address.country` | string \| null | | `contacts.registrant.role` | string | | `contacts.admin` | object | | `contacts.admin.name` | string \| null | | `contacts.admin.organization` | string \| null | | `contacts.admin.email` | string \| null | | `contacts.admin.phone` | string \| null | | `contacts.admin.fax` | string \| null | | `contacts.admin.address` | object | | `contacts.admin.address.street` | string \| null | | `contacts.admin.address.city` | string \| null | | `contacts.admin.address.state` | string \| null | | `contacts.admin.address.postal_code` | string \| null | | `contacts.admin.address.country` | string \| null | | `contacts.admin.role` | string | | `contacts.tech` | object | | `contacts.tech.name` | string \| null | | `contacts.tech.organization` | string \| null | | `contacts.tech.email` | string \| null | | `contacts.tech.phone` | string \| null | | `contacts.tech.fax` | string \| null | | `contacts.tech.address` | object | | `contacts.tech.address.street` | string \| null | | `contacts.tech.address.city` | string \| null | | `contacts.tech.address.state` | string \| null | | `contacts.tech.address.postal_code` | string \| null | | `contacts.tech.address.country` | string \| null | | `contacts.tech.role` | string | | `contacts.billing` | object | | `contacts.billing.name` | string \| null | | `contacts.billing.organization` | string \| null | | `contacts.billing.email` | string \| null | | `contacts.billing.phone` | string \| null | | `contacts.billing.fax` | string \| null | | `contacts.billing.address` | object | | `contacts.billing.address.street` | string \| null | | `contacts.billing.address.city` | string \| null | | `contacts.billing.address.state` | string \| null | | `contacts.billing.address.postal_code` | string \| null | | `contacts.billing.address.country` | string \| null | | `contacts.billing.role` | string | | `privacy` | object | | `privacy.is_private` | boolean | | `privacy.privacy_service` | string \| null | | `privacy.detected_patterns[]` | string[] | | `raw_rdap_link` | string \| null | | `raw_whois` | string \| null | | `abuse_contact` | object \| null | | `registry_domain_id` | string \| null | | `registrar_whois_server` | string \| null | | `traditional_contacts` | object | | `nameserver_ips[]` | object[] | | `nameserver_ips[]` | object | | `nameserver_ips[].name` | string | | `nameserver_ips[].ipv4` | string \| null | | `nameserver_ips[].ipv6` | string \| null | | `checked_at` | string | | `query_time_ms` | integer | | `summary` | object | | `edge_summary` | object | | `edge_summary.relay_configured` | boolean | | `edge_summary.data_sources[]` | string[] | | `edge_summary.authoritative_source` | string | | `edge_summary.relay_whois_used` | boolean | | `edge_summary.raw_whois_available` | boolean | | `edge_summary.parse_error_count` | integer \| null | | `edge_summary.registered` | boolean \| null | | `edge_summary.available` | boolean \| null | | `edge_summary.registration_age_days` | integer \| null | | `edge_summary.days_until_expiry` | integer \| null | | `edge_summary.expires_within_30_days` | boolean \| null | | `edge_summary.transfer_locked` | boolean \| null | | `edge_summary.privacy_protected` | boolean \| null | | `edge_summary.dnssec` | boolean \| null | | `edge_summary.nameserver_count` | integer | | `edge_summary.contact_roles_available[]` | string[] | | `edge_summary.abuse_contact_available` | boolean | | `edge_summary.registrar_whois_server` | string \| null | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v2/whois?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v2/whois?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v2/whois?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v2/whois?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v2/whois?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "registrar": "Example Registrar, Inc.", "registrar_url": "https://registrar.example.net", "registrar_iana_id": "9999", "created_date": "2019-03-11T14:22:08Z", "updated_date": "2026-03-10T09:41:55Z", "expiry_date": "2027-03-11T14:22:08Z", "domain_age_days": 2769, "domain_age_years": 7, "is_newly_registered": false, "days_until_expiry": 153, "transfer_locked": true, "status": [ "client transfer prohibited" ], "nameservers": [ "ns1.example.net", "ns2.example.net" ], "dnssec": false, "contacts": { "registrant": null, "admin": null, "tech": null, "billing": null }, "privacy": { "is_private": false, "privacy_service": null, "detected_patterns": [] }, "raw_rdap_link": "https://rdap.example.net/domain/example.com", "checked_at": "2026-10-09T10:15:30.000Z", "query_time_ms": 412, "registered": true, "summary": { "has_registrant": false, "has_admin": false, "has_tech": false, "has_billing": false, "contact_count": 0, "is_privacy_protected": false }, "abuse_contact": { "email": "abuse@registrar.example.net", "phone": "+1.5555550100" }, "registry_domain_id": "2336799_DOMAIN_COM-VRSN", "registrar_whois_server": "whois.registrar.example.net", "raw_whois": "Domain Name: EXAMPLE.COM\nRegistry Domain ID: 2336799_DOMAIN_COM-VRSN\nRegistrar WHOIS Server: whois.registrar.example.net\nCreation Date: 2019-03-11T14:22:08Z\n...", "nameserver_ips": [ { "name": "ns1.example.net", "ipv4": "192.0.2.53", "ipv6": null } ], "edge_summary": { "relay_configured": true, "data_sources": [ "rdap", "whois" ], "authoritative_source": "whois", "relay_whois_used": true, "raw_whois_available": true, "parse_error_count": 0, "registered": true, "available": false, "registration_age_days": 2769, "days_until_expiry": 153, "expires_within_30_days": false, "transfer_locked": true, "privacy_protected": false, "dnssec": false, "nameserver_count": 2, "contact_roles_available": [], "abuse_contact_available": true, "registrar_whois_server": "whois.registrar.example.net" }, "meta": { "served_by": "pop=MAD country=ES", "data_sources": [ "rdap", "whois" ], "note": "Contact information may be redacted due to privacy regulations (GDPR)" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## POST `/v1/whois/bulk` Operation: `bulkWhois` Credits and authentication: 3 Authentication required POST /v1/whois/bulk Credits: 3/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `results[].domain` | string | | `results[].registered` | boolean \| null | | `results[].available` | boolean \| null | | `results[].availability_reason` | string | | `results[].registrar` | string \| null | | `results[].registrar_url` | string \| null | | `results[].registrar_iana_id` | string \| null | | `results[].created_date` | string \| null | | `results[].updated_date` | string \| null | | `results[].expiry_date` | string \| null | | `results[].domain_age_days` | integer \| null | | `results[].domain_age_years` | integer \| null | | `results[].is_newly_registered` | boolean | | `results[].days_until_expiry` | integer \| null | | `results[].transfer_locked` | boolean | | `results[].nameservers[]` | string[] | | `results[].status[]` | string[] | | `results[].dnssec` | boolean | | `results[].contacts` | object | | `results[].contacts.registrant` | object | | `results[].contacts.registrant.name` | string \| null | | `results[].contacts.registrant.organization` | string \| null | | `results[].contacts.registrant.email` | string \| null | | `results[].contacts.registrant.phone` | string \| null | | `results[].contacts.registrant.fax` | string \| null | | `results[].contacts.registrant.address` | object | | `results[].contacts.registrant.address.street` | string \| null | | `results[].contacts.registrant.address.city` | string \| null | | `results[].contacts.registrant.address.state` | string \| null | | `results[].contacts.registrant.address.postal_code` | string \| null | | `results[].contacts.registrant.address.country` | string \| null | | `results[].contacts.registrant.role` | string | | `results[].contacts.admin` | object | | `results[].contacts.admin.name` | string \| null | | `results[].contacts.admin.organization` | string \| null | | `results[].contacts.admin.email` | string \| null | | `results[].contacts.admin.phone` | string \| null | | `results[].contacts.admin.fax` | string \| null | | `results[].contacts.admin.address` | object | | `results[].contacts.admin.address.street` | string \| null | | `results[].contacts.admin.address.city` | string \| null | | `results[].contacts.admin.address.state` | string \| null | | `results[].contacts.admin.address.postal_code` | string \| null | | `results[].contacts.admin.address.country` | string \| null | | `results[].contacts.admin.role` | string | | `results[].contacts.tech` | object | | `results[].contacts.tech.name` | string \| null | | `results[].contacts.tech.organization` | string \| null | | `results[].contacts.tech.email` | string \| null | | `results[].contacts.tech.phone` | string \| null | | `results[].contacts.tech.fax` | string \| null | | `results[].contacts.tech.address` | object | | `results[].contacts.tech.address.street` | string \| null | | `results[].contacts.tech.address.city` | string \| null | | `results[].contacts.tech.address.state` | string \| null | | `results[].contacts.tech.address.postal_code` | string \| null | | `results[].contacts.tech.address.country` | string \| null | | `results[].contacts.tech.role` | string | | `results[].contacts.billing` | object | | `results[].contacts.billing.name` | string \| null | | `results[].contacts.billing.organization` | string \| null | | `results[].contacts.billing.email` | string \| null | | `results[].contacts.billing.phone` | string \| null | | `results[].contacts.billing.fax` | string \| null | | `results[].contacts.billing.address` | object | | `results[].contacts.billing.address.street` | string \| null | | `results[].contacts.billing.address.city` | string \| null | | `results[].contacts.billing.address.state` | string \| null | | `results[].contacts.billing.address.postal_code` | string \| null | | `results[].contacts.billing.address.country` | string \| null | | `results[].contacts.billing.role` | string | | `results[].privacy` | object | | `results[].privacy.is_private` | boolean | | `results[].privacy.privacy_service` | string \| null | | `results[].privacy.detected_patterns[]` | string[] | | `results[].raw_rdap_link` | string \| null | | `results[].raw_whois` | string \| null | | `results[].abuse_contact` | object \| null | | `results[].registry_domain_id` | string \| null | | `results[].registrar_whois_server` | string \| null | | `results[].traditional_contacts` | object | | `results[].nameserver_ips[]` | object[] | | `results[].nameserver_ips[]` | object | | `results[].nameserver_ips[].name` | string | | `results[].nameserver_ips[].ipv4` | string \| null | | `results[].nameserver_ips[].ipv6` | string \| null | | `results[].checked_at` | string | | `results[].query_time_ms` | integer | | `results[].summary` | object | | `results[].edge_summary` | object | | `results[].edge_summary.relay_configured` | boolean | | `results[].edge_summary.data_sources[]` | string[] | | `results[].edge_summary.authoritative_source` | string | | `results[].edge_summary.relay_whois_used` | boolean | | `results[].edge_summary.raw_whois_available` | boolean | | `results[].edge_summary.parse_error_count` | integer \| null | | `results[].edge_summary.registered` | boolean \| null | | `results[].edge_summary.available` | boolean \| null | | `results[].edge_summary.registration_age_days` | integer \| null | | `results[].edge_summary.days_until_expiry` | integer \| null | | `results[].edge_summary.expires_within_30_days` | boolean \| null | | `results[].edge_summary.transfer_locked` | boolean \| null | | `results[].edge_summary.privacy_protected` | boolean \| null | | `results[].edge_summary.dnssec` | boolean \| null | | `results[].edge_summary.nameserver_count` | integer | | `results[].edge_summary.contact_roles_available[]` | string[] | | `results[].edge_summary.abuse_contact_available` | boolean | | `results[].edge_summary.registrar_whois_server` | string \| null | | `results[].meta` | object | | `total` | integer | | `successful` | integer | | `failed` | integer | | `query_time_ms` | integer | | `meta` | object | | `meta.served_by` | string | | `meta.total` | integer | | `meta.successful` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/whois/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "example.org" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/whois/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "example.org" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/whois/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "example.org", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "example.org" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/whois/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/whois/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "example.org" ] }) #### Example response ```json { "results": [ { "domain": "example.com", "registered": false, "available": true, "availability_reason": "closed_registry", "registrar": "example", "registrar_url": "https://example.com", "registrar_iana_id": "example", "created_date": "2026-08-27T12:00:00Z", "updated_date": "2026-08-27T12:00:00Z", "expiry_date": "2026-08-27T12:00:00Z", "domain_age_days": 1, "domain_age_years": 1, "is_newly_registered": false, "days_until_expiry": 1, "transfer_locked": false, "nameservers": [ "example" ], "status": [ "available" ], "dnssec": false, "contacts": { "registrant": { "name": "example", "organization": "example", "email": "user@example.com", "phone": "+34612345678", "fax": "example", "address": { "street": "example", "city": "example", "state": "example", "postal_code": "example", "country": "US" }, "role": "example" }, "admin": { "name": "example", "organization": "example", "email": "user@example.com", "phone": "+34612345678", "fax": "example", "address": { "street": "example", "city": "example", "state": "example", "postal_code": "example", "country": "US" }, "role": "example" }, "tech": { "name": "example", "organization": "example", "email": "user@example.com", "phone": "+34612345678", "fax": "example", "address": { "street": "example", "city": "example", "state": "example", "postal_code": "example", "country": "US" }, "role": "example" }, "billing": { "name": "example", "organization": "example", "email": "user@example.com", "phone": "+34612345678", "fax": "example", "address": { "street": "example", "city": "example", "state": "example", "postal_code": "example", "country": "US" }, "role": "example" } }, "privacy": { "is_private": false, "privacy_service": "example", "detected_patterns": [ "example" ] }, "raw_rdap_link": "example", "raw_whois": "example", "abuse_contact": {}, "registry_domain_id": "example", "registrar_whois_server": "example", "traditional_contacts": {}, "nameserver_ips": [ { "name": "example", "ipv4": "192.0.2.1", "ipv6": "2001:db8::1" } ], "checked_at": "2026-08-27T12:00:00Z", "query_time_ms": 1, "summary": {}, "edge_summary": { "relay_configured": false, "data_sources": [ "rdap" ], "authoritative_source": "rdap", "relay_whois_used": false, "raw_whois_available": true, "parse_error_count": 1, "registered": false, "available": true, "registration_age_days": 1, "days_until_expiry": 1, "expires_within_30_days": false, "transfer_locked": false, "privacy_protected": false, "dnssec": false, "nameserver_count": 1, "contact_roles_available": [ "example" ], "abuse_contact_available": true, "registrar_whois_server": "example" }, "meta": {} } ], "total": 1, "successful": 1, "failed": 1, "query_time_ms": 1, "meta": { "served_by": "example", "total": 1, "successful": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/whois/history` Operation: `getWhoisHistory` Credits and authentication: 3 Authentication required GET /v1/whois/history Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | limit | integer Default `50` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `domain` | string | | `total_snapshots` | integer | | `first_seen` | string \| null | | `last_seen` | string \| null | | `snapshots[]` | object[] | | `snapshots[]` | object | | `snapshots[].id` | integer | | `snapshots[].domain` | string | | `snapshots[].registrar` | string \| null | | `snapshots[].registrar_iana_id` | string \| null | | `snapshots[].created_date` | string \| null | | `snapshots[].expiry_date` | string \| null | | `snapshots[].updated_date` | string \| null | | `snapshots[].status[]` | string[] | | `snapshots[].nameservers[]` | string[] | | `snapshots[].dnssec` | boolean | | `snapshots[].transfer_locked` | boolean | | `snapshots[].privacy_protected` | boolean | | `snapshots[].snapshot_date` | string | | `snapshots[].changes_from_previous[]` | object[] | | `snapshots[].changes_from_previous[]` | object | | `snapshots[].changes_from_previous[].field` | string | | `snapshots[].changes_from_previous[].old_value` | string \| null | | `snapshots[].changes_from_previous[].new_value` | string \| null | | `snapshots[].created_at` | string | | `summary` | object | | `summary.registrar_changes` | integer | | `summary.nameserver_changes` | integer | | `summary.expiry_extensions` | integer | | `summary.privacy_toggles` | integer | | `summary.status_changes` | integer | | `lifecycle_drift_summary` | object | | `lifecycle_drift_summary.drift_detected` | boolean | | `lifecycle_drift_summary.change_event_count` | integer | | `lifecycle_drift_summary.latest_change_date` | string \| null | | `lifecycle_drift_summary.registrar_changed` | boolean | | `lifecycle_drift_summary.nameservers_changed` | boolean | | `lifecycle_drift_summary.expiry_extended` | boolean | | `lifecycle_drift_summary.status_changed` | boolean | | `lifecycle_drift_summary.privacy_changed` | boolean | | `lifecycle_drift_summary.transfer_lock_changed` | boolean | | `lifecycle_drift_summary.dnssec_changed` | boolean | | `lifecycle_drift_summary.expiry_extension_days_total` | integer | | `lifecycle_drift_summary.latest_changes[]` | object[] | | `lifecycle_drift_summary.latest_changes[]` | object | | `lifecycle_drift_summary.latest_changes[].field` | string | | `lifecycle_drift_summary.latest_changes[].old_value` | string \| null | | `lifecycle_drift_summary.latest_changes[].new_value` | string \| null | | `lifecycle_drift_summary.current_snapshot` | object | | `lifecycle_drift_summary.current_snapshot.registrar` | string \| null | | `lifecycle_drift_summary.current_snapshot.expiry_date` | string \| null | | `lifecycle_drift_summary.current_snapshot.nameservers[]` | string[] | | `lifecycle_drift_summary.current_snapshot.status[]` | string[] | | `lifecycle_drift_summary.current_snapshot.privacy_protected` | boolean | | `lifecycle_drift_summary.previous_snapshot` | object | | `lifecycle_drift_summary.previous_snapshot.registrar` | string \| null | | `lifecycle_drift_summary.previous_snapshot.expiry_date` | string \| null | | `lifecycle_drift_summary.previous_snapshot.nameservers[]` | string[] | | `lifecycle_drift_summary.previous_snapshot.status[]` | string[] | | `lifecycle_drift_summary.previous_snapshot.privacy_protected` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/whois/history?domain=example.com&limit=50" ``` ```javascript const response = await fetch("https://domscan.net/v1/whois/history?domain=example.com&limit=50", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/whois/history?domain=example.com&limit=50", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/whois/history?domain=example.com&limit=50", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/whois/history?domain=example.com&limit=50") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "total_snapshots": 1, "first_seen": "2026-07-09", "last_seen": "2026-07-09", "snapshots": [ { "id": 42, "domain": "example.com", "registrar": "Example Registrar, Inc.", "registrar_iana_id": "9999", "created_date": "1995-08-14T04:00:00Z", "expiry_date": "2027-08-13T04:00:00Z", "updated_date": "2026-06-01T12:00:00Z", "status": [ "client transfer prohibited" ], "nameservers": [ "a.iana-servers.net", "b.iana-servers.net" ], "dnssec": true, "transfer_locked": true, "privacy_protected": true, "snapshot_date": "2026-07-09", "changes_from_previous": [ { "field": "nameservers", "old_value": "ns1.example.net, ns2.example.net", "new_value": "a.iana-servers.net, b.iana-servers.net" } ], "created_at": "2026-07-09T10:15:30Z" } ], "summary": { "registrar_changes": 1, "nameserver_changes": 1, "expiry_extensions": 1, "privacy_toggles": 1, "status_changes": 1 }, "lifecycle_drift_summary": { "drift_detected": false, "change_event_count": 1, "latest_change_date": "2026-08-27T12:00:00Z", "registrar_changed": false, "nameservers_changed": false, "expiry_extended": false, "status_changed": false, "privacy_changed": false, "transfer_lock_changed": false, "dnssec_changed": false, "expiry_extension_days_total": 1, "latest_changes": [ { "field": "example", "old_value": "example", "new_value": "example" } ], "current_snapshot": { "registrar": "example", "expiry_date": "2026-08-27T12:00:00Z", "nameservers": [ "example" ], "status": [ "available" ], "privacy_protected": false }, "previous_snapshot": { "registrar": "example", "expiry_date": "2026-08-27T12:00:00Z", "nameservers": [ "example" ], "status": [ "available" ], "privacy_protected": false } }, "has_more": false, "next_cursor": "example" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/rdap # RDAP Lookup API Instant RDAP lookup for domains. Pull registrar, status, and expiry data in seconds. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/rdap-api) ## Operations GET `/v1/rdap` [View API reference](https://domscan.net/docs/products/rdap#getRdap) POST `/v1/rdap/bulk` [View API reference](https://domscan.net/docs/products/rdap#bulkGetRdap) ## GET `/v1/rdap` Operation: `getRdap` Credits and authentication: 2 Authentication required GET /v1/rdap Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | query | string | optional | | type | string Allowed values `domain`, `ip`, `autnum` | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `query` | string | | `type` | string | | `status` | string | | `rdap` | object | | `rdap.objectClassName` | string | | `rdap.handle` | string | | `rdap.name` | string | | `rdap.startAddress` | string | | `rdap.endAddress` | string | | `rdap.ipVersion` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/rdap?query=example.com" curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/rdap?type=ip&query=8.8.8.8" curl -G -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/rdap" \ --data "type=ip" \ --data-urlencode "query=2001:4860:4860::8888/128" curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/rdap?type=autnum&query=AS174" ``` #### Example response ```json { "query": "8.8.8.8", "type": "ip", "status": "found", "rdap": { "objectClassName": "ip network", "handle": "NET-8-8-8-0-2", "name": "LVLT-GOGL-8-8-8", "startAddress": "8.8.8.0", "endAddress": "8.8.8.255", "ipVersion": "v4" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/rdap/bulk` Operation: `bulkGetRdap` Credits and authentication: 2 Authentication required POST /v1/rdap/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | queries | string[] | required | | type | string Allowed values `domain`, `ip`, `autnum` Default `domain` | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/rdap/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "queries": [ "example.com", "cloudflare.com" ], "type": "domain" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/rdap/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "queries": [ "example.com", "cloudflare.com" ], "type": "domain" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/rdap/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "queries": [ "example.com", "cloudflare.com", ], "type": "domain", }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "queries": [ "example.com", "cloudflare.com" ], "type": "domain" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/rdap/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/rdap/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "queries" => [ "example.com", "cloudflare.com" ], "type" => "domain" }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-profile # Domain Profile API Get a comprehensive profile of a domain including WHOIS, DNS, and hosting information. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-profile-api) ## Operations GET `/v1/profile` [View API reference](https://domscan.net/docs/products/domain-profile#getDomainProfile) POST `/v1/profile/bulk` [View API reference](https://domscan.net/docs/products/domain-profile#bulkGetDomainProfile) GET `/v1/overview` [View API reference](https://domscan.net/docs/products/domain-profile#getDomainOverview) GET `/v1/popularity` [View API reference](https://domscan.net/docs/products/domain-profile#getDomainPopularity) GET `/v1/popularity/history` [View API reference](https://domscan.net/docs/products/domain-profile#getDomainPopularityHistory) ## GET `/v1/profile` Operation: `getDomainProfile` Credits and authentication: 3 Authentication required GET /v1/profile Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `registered` | boolean \| null | | `registrar` | string \| null | | `registrar_url` | string \| null | | `registrar_iana_id` | string \| null | | `created_date` | string \| null | | `updated_date` | string \| null | | `expiry_date` | string \| null | | `age_days` | integer | | `days_until_expiry` | integer | | `nameservers[]` | string[] | | `status[]` | string[] | | `dnssec` | boolean | | `events[]` | object[] | | `events[]` | object | | `events[].action` | string | | `events[].date` | string | | `contacts` | object | | `contacts.registrant_name` | string \| null | | `contacts.registrant_org` | string \| null | | `contacts.registrant_country` | string \| null | | `contacts.admin_email` | string \| null | | `contacts.tech_email` | string \| null | | `privacy` | object | | `privacy.is_private` | boolean | | `privacy.privacy_service` | string \| null | | `raw_rdap_link` | string \| null | | `source_summary` | object | | `source_summary.source` | string | | `source_summary.authoritative_source` | string | | `source_summary.cache_status` | string | | `source_summary.fallback_used` | boolean | | `source_summary.relay_configured` | boolean | | `source_summary.registered` | boolean \| null | | `source_summary.status_count` | integer | | `source_summary.nameserver_count` | integer | | `source_summary.event_count` | integer | | `source_summary.date_fields_present[]` | string[] | | `source_summary.contact_field_count` | integer | | `source_summary.privacy_detected` | boolean | | `checked_at` | string | | `query_time_ms` | integer | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/profile?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/profile?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/profile?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/profile?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/profile?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "registered": true, "registrar": "Example Registrar, Inc.", "registrar_url": "https://registrar.example.net", "registrar_iana_id": "9999", "created_date": "2019-03-11T14:22:08Z", "updated_date": "2026-03-10T09:41:55Z", "expiry_date": "2027-03-11T14:22:08Z", "age_days": 2769, "days_until_expiry": 153, "status": [ "client transfer prohibited" ], "nameservers": [ "ns1.example.net", "ns2.example.net" ], "dnssec": false, "events": [ { "action": "registration", "date": "2019-03-11T14:22:08Z" }, { "action": "expiration", "date": "2027-03-11T14:22:08Z" }, { "action": "last changed", "date": "2026-03-10T09:41:55Z" } ], "contacts": { "registrant_name": null, "registrant_org": null, "registrant_country": null, "admin_email": null, "tech_email": null }, "privacy": { "is_private": false, "privacy_service": null }, "raw_rdap_link": "https://rdap.example.net/domain/example.com", "source_summary": { "source": "rdap", "authoritative_source": "rdap", "cache_status": "miss", "fallback_used": false, "relay_configured": true, "registered": true, "status_count": 1, "nameserver_count": 2, "event_count": 3, "date_fields_present": [ "created_date", "updated_date", "expiry_date" ], "contact_field_count": 0, "privacy_detected": false }, "checked_at": "2026-10-09T10:15:30.000Z", "query_time_ms": 386, "meta": { "served_by": "pop=MAD country=ES", "cached": false } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/profile/bulk` Operation: `bulkGetDomainProfile` Credits and authentication: 3 Authentication required POST /v1/profile/bulk Credits: 3/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/profile/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "cloudflare.com" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/profile/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "cloudflare.com" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/profile/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "cloudflare.com", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "cloudflare.com" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/profile/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/profile/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "cloudflare.com" ] }) #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/overview` Operation: `getDomainOverview` Credits and authentication: 5 Authentication required GET /v1/overview Credits: 5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `health` | object | | `health.dns_ok` | boolean \| null | | `health.https_ok` | boolean \| null | | `dns` | object | | `dns.has_a` | boolean \| null | | `dns.has_aaaa` | boolean \| null | | `dns.has_mx` | boolean \| null | | `dns.nameservers[]` | string[] | | `registration` | object | | `registration.registered` | boolean \| null | | `registration.registrar` | string \| null | | `registration.created_date` | string \| null | | `registration.expiry_date` | string \| null | | `registration.age_days` | integer \| null | | `registration.days_until_expiry` | integer \| null | | `registration.dnssec` | boolean \| null | | `reputation` | object | | `reputation.score` | number \| null | | `reputation.grade` | string \| null | | `popularity` | object | | `popularity.rank` | integer \| null | | `popularity.bucket` | string \| null | | `component_freshness` | object | | `component_freshness.cache_status` | string | | `component_freshness.checked_at` | string | | `component_freshness.component_count` | integer | | `component_freshness.fresh_component_count` | integer | | `component_freshness.degraded_component_count` | integer | | `component_freshness.components` | object | | `component_freshness.components.health` | object | | `component_freshness.components.health.source` | string | | `component_freshness.components.health.state` | string | | `component_freshness.components.health.checked_at` | string | | `component_freshness.components.health.evidence_count` | integer | | `component_freshness.components.health.reason` | string \| null | | `component_freshness.components.dns` | object | | `component_freshness.components.dns.source` | string | | `component_freshness.components.dns.state` | string | | `component_freshness.components.dns.checked_at` | string | | `component_freshness.components.dns.evidence_count` | integer | | `component_freshness.components.dns.reason` | string \| null | | `component_freshness.components.registration` | object | | `component_freshness.components.registration.source` | string | | `component_freshness.components.registration.state` | string | | `component_freshness.components.registration.checked_at` | string | | `component_freshness.components.registration.evidence_count` | integer | | `component_freshness.components.registration.reason` | string \| null | | `component_freshness.components.reputation` | object | | `component_freshness.components.reputation.source` | string | | `component_freshness.components.reputation.state` | string | | `component_freshness.components.reputation.checked_at` | string | | `component_freshness.components.reputation.evidence_count` | integer | | `component_freshness.components.reputation.reason` | string \| null | | `component_freshness.components.popularity` | object | | `component_freshness.components.popularity.source` | string | | `component_freshness.components.popularity.state` | string | | `component_freshness.components.popularity.checked_at` | string | | `component_freshness.components.popularity.evidence_count` | integer | | `component_freshness.components.popularity.reason` | string \| null | | `query_time_ms` | integer | | `checked_at` | string | | `meta` | object | | `meta.served_by` | string | | `meta.cached` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/overview?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/overview?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/overview?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/overview?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/overview?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "health": { "dns_ok": true, "https_ok": true }, "dns": { "has_a": true, "has_aaaa": true, "has_mx": false, "nameservers": [ "ns1.example.net", "ns2.example.net" ] }, "registration": { "registered": true, "registrar": "Example Registrar, Inc.", "created_date": "2019-03-11T14:22:08Z", "expiry_date": "2027-03-11T14:22:08Z", "age_days": 2769, "days_until_expiry": 153, "dnssec": false }, "reputation": { "score": 82, "grade": "A" }, "popularity": { "rank": 18452, "bucket": "top-100k" }, "component_freshness": { "cache_status": "miss", "checked_at": "2026-10-09T10:15:30.000Z", "component_count": 5, "fresh_component_count": 5, "degraded_component_count": 0, "components": { "health": { "source": "quick_health", "state": "fresh", "checked_at": "2026-10-09T10:15:30.000Z", "evidence_count": 2 }, "dns": { "source": "dns", "state": "fresh", "checked_at": "2026-10-09T10:15:30.000Z", "evidence_count": 4 }, "registration": { "source": "rdap", "state": "fresh", "checked_at": "2026-10-09T10:15:30.000Z", "evidence_count": 7 }, "reputation": { "source": "reputation", "state": "fresh", "checked_at": "2026-10-09T10:15:30.000Z", "evidence_count": 2 }, "popularity": { "source": "popularity", "state": "fresh", "checked_at": "2026-10-09T10:15:30.000Z", "evidence_count": 2 } } }, "query_time_ms": 1840, "checked_at": "2026-10-09T10:15:30.000Z", "meta": { "served_by": "pop=MAD country=ES", "cached": false } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/popularity` Operation: `getDomainPopularity` Credits and authentication: 2 Authentication required GET /v1/popularity Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | include_history | boolean Default `false` | optional | | history_limit | integer Default `30` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `status` | string | | `rank` | integer \| null | | `bucket` | string | | `source` | object | | `source.id` | string | | `source.url` | string | | `source.list_date` | string \| null | | `source.provenance` | object | | `source.provenance.owner` | string | | `source.provenance.source_url` | string | | `source.provenance.methodology_url` | string | | `source.provenance.access_method` | string | | `source.provenance.cost` | string | | `source.provenance.runtime_rate_limits` | string | | `source.provenance.terms_status` | string | | `source.provenance.expected_freshness` | string | | `source.provenance.maintenance_risk` | string | | `source.provenance.fallback_behavior` | string | | `source.provenance.last_verified` | string | | `freshness` | object | | `freshness.cache_status` | string | | `freshness.ttl_seconds` | integer | | `checked_at` | string | | `result_count` | integer \| null | | `empty_result` | boolean | | `history` | object | | `history.collection` | string | | `history.complete_daily_series` | boolean | | `history.available` | boolean | | `history.observations[]` | object[] | | `history.observations[]` | object | | `history.observations[].domain` | string | | `history.observations[].rank` | integer \| null | | `history.observations[].bucket` | string | | `history.observations[].status` | string | | `history.observations[].source` | string | | `history.observations[].list_date` | string \| null | | `history.observations[].observed_on` | string | | `history.observations[].checked_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/popularity?domain=example.com&include_history=false&history_limit=30" ``` ```javascript const response = await fetch("https://domscan.net/v1/popularity?domain=example.com&include_history=false&history_limit=30", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/popularity?domain=example.com&include_history=false&history_limit=30", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/popularity?domain=example.com&include_history=false&history_limit=30", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/popularity?domain=example.com&include_history=false&history_limit=30") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "status": "ranked", "rank": 18452, "bucket": "top-100k", "source": { "id": "tranco", "url": "https://tranco-list.eu/", "list_date": "2026-10-08", "provenance": { "owner": "Tranco research project", "source_url": "https://tranco-list.eu/", "methodology_url": "https://tranco-list.eu/methodology", "access_method": "public_domain_rank_api", "cost": "none", "runtime_rate_limits": "not_published_cached_and_bounded_by_domscan", "terms_status": "mixed_upstream_licenses_review_required_for_commercial_reuse", "expected_freshness": "daily", "maintenance_risk": "medium", "fallback_behavior": "return_unknown_without_inventing_or_reusing_an_unranked_result", "last_verified": "2026-08-02" } }, "freshness": { "cache_status": "miss", "ttl_seconds": 86400 }, "checked_at": "2026-10-09T10:15:30.000Z", "result_count": 1, "empty_result": false, "history": { "collection": "lookup_driven", "complete_daily_series": false, "available": true, "observations": [ { "domain": "example.com", "rank": 18452, "bucket": "top-100k", "status": "ranked", "source": "tranco", "list_date": "2026-10-08", "observed_on": "2026-10-09", "checked_at": "2026-10-09T10:15:30.000Z" }, { "domain": "example.com", "rank": 18877, "bucket": "top-100k", "status": "ranked", "source": "tranco", "list_date": "2026-10-01", "observed_on": "2026-10-02", "checked_at": "2026-10-02T10:15:30.000Z" } ] } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/popularity/history` Operation: `getDomainPopularityHistory` Credits and authentication: 1 Authentication required GET /v1/popularity/history Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | limit | integer Default `30` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `collection` | string | | `complete_daily_series` | boolean | | `result_count` | integer | | `empty_result` | boolean | | `observations[]` | object[] | | `observations[]` | object | | `observations[].domain` | string | | `observations[].rank` | integer \| null | | `observations[].bucket` | string | | `observations[].status` | string | | `observations[].source` | string | | `observations[].list_date` | string \| null | | `observations[].observed_on` | string | | `observations[].checked_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/popularity/history?domain=example.com&limit=25" ``` ```javascript const response = await fetch("https://domscan.net/v1/popularity/history?domain=example.com&limit=25", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/popularity/history?domain=example.com&limit=25", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/popularity/history?domain=example.com&limit=25", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/popularity/history?domain=example.com&limit=25") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "collection": "lookup_driven", "complete_daily_series": false, "result_count": 1, "empty_result": false, "observations": [ { "domain": "example.com", "rank": 1, "bucket": "top-100", "status": "ranked", "source": "tranco", "list_date": "2026-08-27", "observed_on": "2026-08-27", "checked_at": "2026-08-27T12:00:00Z" } ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `500` Server Error ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/dns-lookup # DNS Lookup API Perform DNS lookups for any record type. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/dns-lookup-api) ## Operations GET `/v1/dns` [View API reference](https://domscan.net/docs/products/dns-lookup#getDnsRecords) GET `/v1/dns/all` [View API reference](https://domscan.net/docs/products/dns-lookup#getAllDnsRecords) GET `/v1/dns/history` [View API reference](https://domscan.net/docs/products/dns-lookup#getDnsHistory) ## GET `/v1/dns` Operation: `getDnsRecords` Credits and authentication: 1 Authentication required GET /v1/dns Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | type | string Allowed values `A`, `AAAA`, `MX`, `NS`, `TXT`, `SOA`, `CNAME`, `CAA`, `PTR`, `SRV`, `ALL` Default `A` | optional | #### Response fields #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns?domain=example.com&type=A" ``` ```javascript const response = await fetch("https://domscan.net/v1/dns?domain=example.com&type=A", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/dns?domain=example.com&type=A", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/dns?domain=example.com&type=A", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns?domain=example.com&type=A") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "google.com", "record_type": "TXT", "records": [ { "type": "TXT", "name": "google.com", "data": "v=spf1 include:_spf.google.com ~all", "ttl": 300, "classification": "spf" }, { "type": "TXT", "name": "google.com", "data": "google-site-verification=abc123", "ttl": 300, "classification": "verification" } ], "status": "success", "dnssec_validated": false, "query_time_ms": 37, "checked_at": "2026-04-18T21:00:00Z", "warnings": [ { "code": "TXT_MULTIPLE_RESPONSES", "message": "Domain publishes multiple TXT records; use classification to isolate the security ones.", "severity": "info" } ], "meta": { "served_by": "pop=unknown country=unknown" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/dns/all` Operation: `getAllDnsRecords` Credits and authentication: 2 Authentication required GET /v1/dns/all Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | wildcard_probe | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `records` | object | | `summary` | object | | `summary.has_a` | boolean | | `summary.has_aaaa` | boolean | | `summary.has_ns` | boolean | | `summary.has_mx` | boolean | | `summary.has_txt` | boolean | | `summary.has_https` | boolean | | `summary.has_svcb` | boolean | | `summary.ipv6_parity` | string | | `warnings[]` | object[] | | `warnings[]` | object | | `warnings[].code` | string | | `warnings[].message` | string | | `warnings[].severity` | string | | `wildcard` | object | | `wildcard.suspected` | boolean | | `wildcard.probe_label` | string | | `query_time_ms` | integer | | `checked_at` | string | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns/all?domain=example.com&wildcard_probe=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/dns/all?domain=example.com&wildcard_probe=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/dns/all?domain=example.com&wildcard_probe=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/dns/all?domain=example.com&wildcard_probe=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns/all?domain=example.com&wildcard_probe=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "openai.com", "records": { "A": [ { "type": "A", "name": "openai.com", "data": "104.18.33.45", "ttl": 300 } ], "AAAA": [ { "type": "AAAA", "name": "openai.com", "data": "2606:4700::6812:212d", "ttl": 300 } ], "MX": [ { "type": "MX", "name": "openai.com", "data": "aspmx.l.google.com", "ttl": 300, "priority": 1 } ], "NS": [ { "type": "NS", "name": "openai.com", "data": "ns1-02.azure-dns.com", "ttl": 172800 }, { "type": "NS", "name": "openai.com", "data": "ns2-02.azure-dns.net", "ttl": 172800 } ], "TXT": [ { "type": "TXT", "name": "openai.com", "data": "v=spf1 include:_spf.google.com ~all", "ttl": 300, "classification": "spf" }, { "type": "TXT", "name": "openai.com", "data": "v=TLSRPTv1; rua=mailto:tlsrpt@openai.com", "ttl": 300, "classification": "tls_rpt" } ] }, "summary": { "has_a": true, "has_aaaa": true, "has_ns": true, "has_mx": true, "has_txt": true, "has_https": false, "has_svcb": false, "ipv6_parity": "full" }, "warnings": [ { "code": "MX_PRIORITY_SHARED", "message": "Multiple MX hosts share the same priority.", "severity": "info" } ], "wildcard": { "suspected": false, "probe_label": "_domscan-probe-4f6a2c.openai.com" }, "query_time_ms": 82, "checked_at": "2026-04-18T21:00:00Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/dns/history` Operation: `getDnsHistory` Credits and authentication: 3 Authentication required GET /v1/dns/history Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | type | string | optional | | from | string | optional | | to | string | optional | | limit | integer Default `100` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `domain` | string | | `history[]` | object[] | | `history[]` | object | | `history[].date` | string | | `history[].record_type` | string | | `history[].changes[]` | object[] | | `history[].changes[]` | object | | `history[].changes[].action` | string | | `history[].changes[].value` | string | | `history[].changes[].ttl` | integer \| null | | `current_records` | object | | `first_seen` | string \| null | | `last_seen` | string \| null | | `total_changes` | integer | | `record_types_tracked[]` | string[] | | `beta_notice` | string | | `meta` | object | | `meta.note` | string | | `meta.data_source` | string | | `meta.history_limit` | integer | | `meta.history_rows_evaluated` | integer | | `meta.history_rows_truncated` | boolean | | `meta.removal_confirmation_days` | integer | | `meta.current_records_scope` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns/history?domain=example.com&type=A&from=2026-01-01&to=2026-04-15&limit=10" ``` ```javascript const response = await fetch("https://domscan.net/v1/dns/history?domain=example.com&type=A&from=2026-01-01&to=2026-04-15&limit=10", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/dns/history?domain=example.com&type=A&from=2026-01-01&to=2026-04-15&limit=10", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/dns/history?domain=example.com&type=A&from=2026-01-01&to=2026-04-15&limit=10", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns/history?domain=example.com&type=A&from=2026-01-01&to=2026-04-15&limit=10") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "history": [ { "date": "2026-04-13", "record_type": "A", "changes": [ { "action": "added", "value": "104.20.23.154" }, { "action": "added", "value": "172.66.147.243" }, { "action": "removed", "value": "104.18.26.120" } ] } ], "current_records": { "A": [ "104.20.23.154", "172.66.147.243" ] }, "first_seen": "2026-01-01", "last_seen": "2026-04-13", "total_changes": 3, "record_types_tracked": [ "A" ], "beta_notice": "Beta observation log. Coverage comes only from successful DomScan DNS lookups. Dates are day-level, changes between lookups can be missed, and no external passive DNS sources are included.", "meta": { "note": "Lookup-driven DomScan observations only. Dates are day-level, gaps can miss changes, and no external passive DNS sources are included.", "data_source": "internal", "history_limit": 100, "history_rows_evaluated": 3, "history_rows_truncated": false, "removal_confirmation_days": 2, "current_records_scope": "all_stored_current_records" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/dns-security # DNS Security Analysis API Analyze DNS security configuration including DNSSEC, SPF, DKIM, DMARC, and other security records. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/dns-security) ## Operations GET `/v1/dns/security` [View API reference](https://domscan.net/docs/products/dns-security#getDnsSecurity) ## GET `/v1/dns/security` Operation: `getDnsSecurity` Credits and authentication: 3 Authentication required GET /v1/dns/security Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `security_score` | integer \| null | | `security_grade` | string \| null | | `checks_unknown` | integer | | `score_confidence` | string | | `spf` | object | | `spf.classification` | object | | `spf.classification.status` | string | | `spf.classification.reason` | string | | `spf.classification.evidence` | object | | `spf.classification.evidence.source` | string | | `spf.classification.evidence.method` | string | | `spf.classification.evidence.observed_at` | string | | `spf.classification.evidence.detail` | string | | `spf.classification.checked_at` | string | | `spf.exists` | boolean \| null | | `spf.record` | string | | `spf.valid` | boolean | | `spf.policy` | string | | `spf.includes[]` | string[] | | `spf.dns_lookup_count` | integer | | `spf.dns_lookup_limit_exceeded` | boolean | | `spf.include_tree[]` | object[] | | `spf.include_tree[]` | object | | `spf.include_tree[].domain` | string | | `spf.include_tree[].lookups` | integer | | `spf.lookup_walk_count` | integer | | `spf.macros_present` | boolean | | `spf.macro_references[]` | string[] | | `spf.walk[]` | object[] | | `spf.walk[]` | object | | `spf.walk[].domain` | string | | `spf.walk[].depth` | integer | | `spf.walk[].record` | string | | `spf.walk[].mechanisms[]` | string[] | | `spf.walk[].includes[]` | string[] | | `spf.walk[].redirect` | string \| null | | `spf.walk[].direct_lookup_count` | integer | | `spf.walk[].total_lookup_count` | integer | | `spf.walk[].macros_present` | boolean | | `spf.walk[].macro_references[]` | string[] | | `spf.walk[].multiple_records` | integer | | `spf.walk_errors[]` | string[] | | `spf.lookup_tree` | object | | `spf.lookup_tree.root_domain` | string | | `spf.lookup_tree.node_count` | integer | | `spf.lookup_tree.max_depth` | integer | | `spf.lookup_tree.cycles_detected[]` | string[] | | `spf.lookup_tree.nodes[]` | object[] | | `spf.lookup_tree.nodes[]` | object | | `spf.lookup_tree.nodes[].domain` | string | | `spf.lookup_tree.nodes[].depth` | integer | | `spf.lookup_tree.nodes[].status` | string | | `spf.lookup_tree.nodes[].direct_lookup_count` | integer | | `spf.lookup_tree.nodes[].total_lookup_count` | integer | | `spf.lookup_tree.nodes[].includes[]` | string[] | | `spf.lookup_tree.nodes[].redirect` | string \| null | | `spf.lookup_tree.nodes[].mechanisms[]` | string[] | | `spf.lookup_tree.nodes[].errors[]` | string[] | | `spf.lookup_tree.edges[]` | object[] | | `spf.lookup_tree.edges[]` | object | | `spf.lookup_tree.edges[].from` | string | | `spf.lookup_tree.edges[].to` | string | | `spf.lookup_tree.edges[].type` | string | | `spf.issues[]` | string[] | | `dkim` | object | | `dkim.classification` | object | | `dkim.classification.status` | string | | `dkim.classification.reason` | string | | `dkim.classification.evidence` | object | | `dkim.classification.evidence.source` | string | | `dkim.classification.evidence.method` | string | | `dkim.classification.evidence.observed_at` | string | | `dkim.classification.evidence.detail` | string | | `dkim.classification.checked_at` | string | | `dkim.exists` | boolean \| null | | `dkim.selectors_checked[]` | string[] | | `dkim.selectors_found[]` | string[] | | `dkim.valid` | boolean | | `dmarc` | object | | `dmarc.classification` | object | | `dmarc.classification.status` | string | | `dmarc.classification.reason` | string | | `dmarc.classification.evidence` | object | | `dmarc.classification.evidence.source` | string | | `dmarc.classification.evidence.method` | string | | `dmarc.classification.evidence.observed_at` | string | | `dmarc.classification.evidence.detail` | string | | `dmarc.classification.checked_at` | string | | `dmarc.exists` | boolean \| null | | `dmarc.record` | string | | `dmarc.valid` | boolean | | `dmarc.policy` | string | | `dmarc.subdomain_policy` | string | | `dmarc.percentage` | integer | | `dmarc.rua[]` | string[] | | `dmarc.ruf[]` | string[] | | `dmarc.issues[]` | string[] | | `bimi` | object | | `bimi.classification` | object | | `bimi.classification.status` | string | | `bimi.classification.reason` | string | | `bimi.classification.evidence` | object | | `bimi.classification.evidence.source` | string | | `bimi.classification.evidence.method` | string | | `bimi.classification.evidence.observed_at` | string | | `bimi.classification.evidence.detail` | string | | `bimi.classification.checked_at` | string | | `bimi.exists` | boolean \| null | | `bimi.record` | string | | `bimi.logo_url` | string | | `bimi.authority_url` | string | | `bimi.valid` | boolean | | `bimi.logo_fetch_ok` | boolean \| null | | `bimi.logo_http_status` | integer \| null | | `bimi.logo_content_type` | string \| null | | `bimi.logo_bytes` | integer \| null | | `bimi.logo_svg_detected` | boolean \| null | | `bimi.vmc_present` | boolean | | `bimi.vmc_fetched` | boolean \| null | | `bimi.vmc_http_status` | integer \| null | | `bimi.vmc_content_type` | string \| null | | `bimi.vmc_certificate_valid` | boolean \| null | | `bimi.vmc_subject` | string \| null | | `bimi.vmc_issuer` | string \| null | | `bimi.vmc_not_before` | string \| null | | `bimi.vmc_not_after` | string \| null | | `bimi.vmc_days_to_expiry` | integer \| null | | `bimi.vmc_fingerprint_sha256` | string \| null | | `bimi.vmc_san_domains[]` | string[] | | `bimi.errors[]` | string[] | | `dnssec` | object | | `dnssec.classification` | object | | `dnssec.classification.status` | string | | `dnssec.classification.reason` | string | | `dnssec.classification.evidence` | object | | `dnssec.classification.evidence.source` | string | | `dnssec.classification.evidence.method` | string | | `dnssec.classification.evidence.observed_at` | string | | `dnssec.classification.evidence.detail` | string | | `dnssec.classification.checked_at` | string | | `dnssec.enabled` | boolean \| null | | `dnssec.valid` | boolean | | `dnssec.algorithm` | string | | `dnssec.key_tag` | integer | | `dnssec.validation_status` | string | | `dnssec.validated_by_proxy` | boolean | | `dnssec.validation_reason` | string \| null | | `dnssec.ds_records[]` | string[] | | `dnssec.dnskey_records[]` | string[] | | `dnssec.rrsig_present` | boolean | | `dnssec.resolver` | string | | `dnssec.mismatch_detail` | object | | `dnssec.mismatch_detail.checked` | boolean | | `dnssec.mismatch_detail.mismatch_detected` | boolean | | `dnssec.mismatch_detail.reason` | string \| null | | `dnssec.mismatch_detail.ds_record_count` | integer | | `dnssec.mismatch_detail.dnskey_record_count` | integer | | `dnssec.mismatch_detail.rrsig_present` | boolean \| null | | `dnssec.mismatch_detail.validation_status` | string \| null | | `dnssec.mismatch_detail.resolver` | string \| null | | `caa` | object | | `caa.classification` | object | | `caa.classification.status` | string | | `caa.classification.reason` | string | | `caa.classification.evidence` | object | | `caa.classification.evidence.source` | string | | `caa.classification.evidence.method` | string | | `caa.classification.evidence.observed_at` | string | | `caa.classification.evidence.detail` | string | | `caa.classification.checked_at` | string | | `caa.exists` | boolean \| null | | `caa.records[]` | object[] | | `caa.records[]` | object | | `caa.records[].flags` | integer | | `caa.records[].tag` | string | | `caa.records[].value` | string | | `caa.issuers[]` | string[] | | `caa.issue_wild[]` | string[] | | `caa.iodef` | string | | `issuance_readiness` | object | | `issuance_readiness.caa` | object | | `issuance_readiness.caa.exists` | boolean | | `issuance_readiness.caa.records[]` | object[] | | `issuance_readiness.caa.records[]` | object | | `issuance_readiness.caa.records[].flags` | integer | | `issuance_readiness.caa.records[].tag` | string | | `issuance_readiness.caa.records[].value` | string | | `issuance_readiness.caa.issue_issuers[]` | string[] | | `issuance_readiness.caa.issuewild_issuers[]` | string[] | | `issuance_readiness.caa.iodef` | string \| null | | `issuance_readiness.caa.letsencrypt_allowed` | boolean | | `issuance_readiness.caa.google_trust_services_allowed` | boolean | | `issuance_readiness.http01` | object | | `issuance_readiness.http01.challenge_path` | string | | `issuance_readiness.http01.reachable` | boolean | | `issuance_readiness.http01.ready` | boolean | | `issuance_readiness.http01.status_code` | integer \| null | | `issuance_readiness.http01.final_url` | string \| null | | `issuance_readiness.http01.redirects` | integer \| null | | `issuance_readiness.http01.error` | string \| null | | `issuance_readiness.checked_at` | string | | `authoritative_consistency` | object | | `authoritative_consistency.record_type` | string | | `authoritative_consistency.all_authoritative` | boolean | | `authoritative_consistency.answer_sets_match` | boolean | | `authoritative_consistency.inconsistent_nameservers[]` | string[] | | `authoritative_consistency.consistent_serial` | boolean | | `authoritative_consistency.serials[]` | object[] | | `authoritative_consistency.serials[]` | object | | `authoritative_consistency.serials[].host` | string | | `authoritative_consistency.serials[].udp_soa_serial` | string \| null | | `authoritative_consistency.serials[].tcp_soa_serial` | string \| null | | `authoritative_consistency.reference_answers[]` | string[] | | `delegation_health` | object | | `delegation_health.nameservers[]` | object[] | | `delegation_health.nameservers[]` | object | | `delegation_health.nameservers[].host` | string | | `delegation_health.nameservers[].addresses[]` | string[] | | `delegation_health.nameservers[].in_bailiwick` | boolean | | `delegation_health.nameservers[].glue_required` | boolean | | `delegation_health.nameservers[].udp` | object | | `delegation_health.nameservers[].udp.authoritative` | boolean | | `delegation_health.nameservers[].udp.status` | string | | `delegation_health.nameservers[].udp.query_ms` | integer \| null | | `delegation_health.nameservers[].udp.answer_count` | integer | | `delegation_health.nameservers[].udp.answers[]` | string[] | | `delegation_health.nameservers[].udp.soa_serial` | string \| null | | `delegation_health.nameservers[].udp.truncated` | boolean | | `delegation_health.nameservers[].udp.error` | string \| null | | `delegation_health.nameservers[].tcp` | object | | `delegation_health.nameservers[].tcp.authoritative` | boolean | | `delegation_health.nameservers[].tcp.status` | string | | `delegation_health.nameservers[].tcp.query_ms` | integer \| null | | `delegation_health.nameservers[].tcp.answer_count` | integer | | `delegation_health.nameservers[].tcp.answers[]` | string[] | | `delegation_health.nameservers[].tcp.soa_serial` | string \| null | | `delegation_health.nameservers[].tcp.truncated` | boolean | | `delegation_health.nameservers[].tcp.error` | string \| null | | `delegation_health.nameservers[].lame` | boolean | | `delegation_health.nameservers[].issues[]` | string[] | | `delegation_health.in_bailiwick_nameservers[]` | string[] | | `delegation_health.glue_required_count` | integer | | `delegation_health.all_in_bailiwick_resolve` | boolean | | `delegation_health.missing_addresses[]` | string[] | | `delegation_health.lame_nameservers[]` | string[] | | `dns_transport` | object | | `dns_transport.udp_working` | boolean | | `dns_transport.tcp_working` | boolean | | `dns_transport.tcp_supported_nameservers[]` | string[] | | `dns_transport.tcp_failed_nameservers[]` | string[] | | `dns_transport.truncation_tested` | boolean | | `dns_transport.truncation_nameserver` | string | | `dns_transport.truncation_record_type` | string | | `dns_transport.truncation_observed` | boolean \| null | | `dns_transport.tcp_fallback_ready` | boolean \| null | | `nameserver_drift` | object | | `nameserver_drift.checked` | boolean | | `nameserver_drift.drift_detected` | boolean \| null | | `nameserver_drift.public_nameservers[]` | string[] | | `nameserver_drift.authoritative_nameservers[]` | string[] | | `nameserver_drift.missing_from_authority[]` | string[] | | `nameserver_drift.extra_at_authority[]` | string[] | | `nameserver_drift.inconsistent_nameservers[]` | string[] | | `nameserver_drift.serial_mismatch_detected` | boolean \| null | | `mta_sts` | object | | `mta_sts.classification` | object | | `mta_sts.classification.status` | string | | `mta_sts.classification.reason` | string | | `mta_sts.classification.evidence` | object | | `mta_sts.classification.evidence.source` | string | | `mta_sts.classification.evidence.method` | string | | `mta_sts.classification.evidence.observed_at` | string | | `mta_sts.classification.evidence.detail` | string | | `mta_sts.classification.checked_at` | string | | `mta_sts.exists` | boolean \| null | | `mta_sts.record` | string | | `mta_sts.valid` | boolean | | `mta_sts.policy_id` | string | | `mta_sts.policy_fetch_ok` | boolean | | `mta_sts.policy_http_status` | integer \| null | | `mta_sts.mode` | string | | `mta_sts.max_age` | integer | | `mta_sts.mx_hosts[]` | string[] | | `mta_sts.mx_records[]` | string[] | | `mta_sts.policy_matches_mx` | boolean \| null | | `mta_sts.uncovered_mx[]` | string[] | | `mta_sts.errors[]` | string[] | | `tls_rpt` | object | | `tls_rpt.exists` | boolean | | `tls_rpt.record` | string | | `tls_rpt.valid` | boolean | | `tls_rpt.rua[]` | string[] | | `tls_rpt.errors[]` | string[] | | `resolver_latency` | object | | `resolver_latency.record_type` | string | | `resolver_latency.resolvers[]` | object[] | | `resolver_latency.resolvers[]` | object | | `resolver_latency.resolvers[].resolver` | string | | `resolver_latency.resolvers[].label` | string | | `resolver_latency.resolvers[].query_ms` | integer \| null | | `resolver_latency.resolvers[].status` | string | | `resolver_latency.resolvers[].answer_count` | integer | | `resolver_latency.resolvers[].answers[]` | string[] | | `resolver_latency.resolvers[].server` | string \| null | | `resolver_latency.resolvers[].error` | string \| null | | `resolver_latency.min_ms` | integer \| null | | `resolver_latency.max_ms` | integer \| null | | `resolver_latency.avg_ms` | number \| null | | `zone_transfer` | object | | `zone_transfer.exposed` | boolean | | `zone_transfer.nameservers[]` | object[] | | `zone_transfer.nameservers[]` | object | | `zone_transfer.nameservers[].host` | string | | `zone_transfer.nameservers[].exposed` | boolean | | `zone_transfer.nameservers[].query_ms` | integer | | `zone_transfer.nameservers[].records_returned` | integer | | `zone_transfer.nameservers[].soa_seen` | boolean | | `zone_transfer.nameservers[].reason` | string \| null | | `zone_transfer.nameservers[].sample_records[]` | string[] | | `blacklist` | object | | `blacklist.domain` | string | | `blacklist.listed` | boolean | | `blacklist.lists[]` | object[] | | `blacklist.lists[]` | object | | `blacklist.lists[].name` | string | | `blacklist.lists[].listed` | boolean | | `blacklist.lists[].code` | string | | `blacklist.lists[].meaning` | string | | `blacklist.threat_level` | string | | `blacklist.check_type` | string | | `blacklist.checked_at` | string | | `edge_summary` | object | | `edge_summary.relay_configured` | boolean | | `edge_summary.evidence_sources[]` | string[] | | `edge_summary.secure_dns_chain` | boolean | | `edge_summary.zone_transfer_exposed` | boolean \| null | | `edge_summary.authoritative_consistency_ok` | boolean \| null | | `edge_summary.nameserver_drift_detected` | boolean \| null | | `edge_summary.lame_nameserver_count` | integer \| null | | `edge_summary.tcp_fallback_ready` | boolean \| null | | `edge_summary.avg_resolver_latency_ms` | number \| null | | `edge_summary.fastest_resolver` | string \| null | | `edge_summary.slowest_resolver` | string \| null | | `edge_summary.issuance_http01_ready` | boolean \| null | | `edge_summary.caa_restricts_issuers` | boolean | | `edge_summary.bimi_vmc_valid` | boolean \| null | | `edge_summary.mta_sts_enforced` | boolean | | `edge_summary.tls_rpt_configured` | boolean | | `edge_summary.spf_lookup_limit_exceeded` | boolean | | `recommendations[]` | string[] | | `checked_at` | string | | `check_duration_ms` | integer | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns/security?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/dns/security?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/dns/security?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/dns/security?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns/security?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "google.com", "security_score": 97, "security_grade": "A+", "spf": { "exists": true, "record": "v=spf1 include:_spf.google.com ~all", "valid": true, "policy": "softfail", "includes": [ "_spf.google.com" ], "dns_lookup_count": 1, "dns_lookup_limit_exceeded": false, "include_tree": [ { "domain": "_spf.google.com", "lookups": 1 } ], "lookup_walk_count": 1, "macros_present": false, "macro_references": [], "walk": [ { "domain": "google.com", "depth": 0, "record": "v=spf1 include:_spf.google.com ~all", "mechanisms": [ "include:_spf.google.com", "~all" ], "includes": [ "_spf.google.com" ], "redirect": null, "direct_lookup_count": 1, "total_lookup_count": 1, "macros_present": false, "macro_references": [], "multiple_records": 1 } ], "walk_errors": [], "issues": [] }, "dkim": { "exists": true, "selectors_checked": [ "google", "selector1", "selector2" ], "selectors_found": [ "google" ], "valid": true }, "dmarc": { "exists": true, "record": "v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com", "valid": true, "policy": "reject", "subdomain_policy": "reject", "percentage": 100, "rua": [ "mailto:mailauth-reports@google.com" ], "ruf": [], "issues": [] }, "bimi": { "exists": true, "record": "v=BIMI1; l=https://example.com/logo.svg; a=https://example.com/vmc.pem", "logo_url": "https://example.com/logo.svg", "authority_url": "https://example.com/vmc.pem", "valid": true, "logo_fetch_ok": true, "logo_http_status": 200, "logo_content_type": "image/svg+xml", "logo_bytes": 2048, "logo_svg_detected": true, "vmc_present": true, "vmc_fetched": true, "vmc_http_status": 200, "vmc_content_type": "application/x-pem-file", "vmc_certificate_valid": true, "vmc_subject": "/CN=Example Inc VMC", "vmc_issuer": "/CN=Example Issuer", "vmc_not_before": "2026-01-01T00:00:00Z", "vmc_not_after": "2027-01-01T00:00:00Z", "vmc_days_to_expiry": 258, "vmc_fingerprint_sha256": "AA:BB:CC:DD", "vmc_san_domains": [ "google.com" ], "errors": [] }, "dnssec": { "enabled": true, "valid": true, "algorithm": "ECDSAP256SHA256", "key_tag": 12345, "validation_status": "secure", "validated_by_proxy": true, "validation_reason": "chain validated via delv", "ds_records": [ "12345 13 2 1a2b3c4d5e6f" ], "dnskey_records": [ "256 3 13 AbCdEfGhIjKlMnOp" ], "rrsig_present": true, "resolver": "127.0.0.1", "mismatch_detail": { "checked": true, "mismatch_detected": false, "reason": "chain validated via delv", "ds_record_count": 1, "dnskey_record_count": 1, "rrsig_present": true, "validation_status": "secure", "resolver": "127.0.0.1" } }, "caa": { "exists": true, "records": [ { "flags": 0, "tag": "issue", "value": "pki.goog" } ], "issuers": [ "pki.goog" ], "issue_wild": [], "iodef": "mailto:security@google.com" }, "issuance_readiness": { "caa": { "exists": true, "records": [ { "flags": 0, "tag": "issue", "value": "pki.goog" }, { "flags": 0, "tag": "iodef", "value": "mailto:security@google.com" } ], "issue_issuers": [ "pki.goog" ], "issuewild_issuers": [], "iodef": "mailto:security@google.com", "letsencrypt_allowed": false, "google_trust_services_allowed": true }, "http01": { "challenge_path": "/.well-known/acme-challenge/domscan-probe-1713474000", "reachable": true, "ready": true, "status_code": 404, "final_url": "http://google.com/.well-known/acme-challenge/domscan-probe-1713474000", "redirects": 0, "error": null }, "checked_at": "2026-04-18T21:00:00Z" }, "authoritative_consistency": { "record_type": "SOA", "all_authoritative": true, "answer_sets_match": true, "inconsistent_nameservers": [], "consistent_serial": true, "serials": [ { "host": "ns1.google.com", "udp_soa_serial": "2026041801", "tcp_soa_serial": "2026041801" } ], "reference_answers": [ "google.com. 60 IN SOA ns1.google.com. dns-admin.google.com. 2026041801 900 900 1800 60" ] }, "delegation_health": { "nameservers": [ { "host": "ns1.google.com", "addresses": [ "216.239.32.10" ], "in_bailiwick": false, "glue_required": false, "udp": { "authoritative": true, "status": "NOERROR", "query_ms": 14, "answer_count": 1, "answers": [ "google.com. 60 IN SOA ns1.google.com. dns-admin.google.com. 2026041801 900 900 1800 60" ], "soa_serial": "2026041801", "truncated": false, "error": null }, "tcp": { "authoritative": true, "status": "NOERROR", "query_ms": 18, "answer_count": 1, "answers": [ "google.com. 60 IN SOA ns1.google.com. dns-admin.google.com. 2026041801 900 900 1800 60" ], "soa_serial": "2026041801", "truncated": false, "error": null }, "lame": false, "issues": [] } ], "in_bailiwick_nameservers": [], "glue_required_count": 0, "all_in_bailiwick_resolve": true, "missing_addresses": [], "lame_nameservers": [] }, "dns_transport": { "udp_working": true, "tcp_working": true, "tcp_supported_nameservers": [ "ns1.google.com" ], "tcp_failed_nameservers": [], "truncation_tested": true, "truncation_nameserver": "ns1.google.com", "truncation_record_type": "DNSKEY", "truncation_observed": false, "tcp_fallback_ready": null }, "nameserver_drift": { "checked": true, "drift_detected": false, "public_nameservers": [ "ns1.google.com" ], "authoritative_nameservers": [ "ns1.google.com" ], "missing_from_authority": [], "extra_at_authority": [], "inconsistent_nameservers": [], "serial_mismatch_detected": false }, "mta_sts": { "exists": true, "record": "v=STSv1; id=2024010101Z", "valid": true, "policy_id": "2024010101Z", "policy_fetch_ok": true, "policy_http_status": 200, "mode": "enforce", "max_age": 86400, "mx_hosts": [ "*.google.com" ], "mx_records": [ "aspmx.l.google.com", "alt1.aspmx.l.google.com" ], "policy_matches_mx": true, "uncovered_mx": [], "errors": [] }, "tls_rpt": { "exists": true, "record": "v=TLSRPTv1; rua=mailto:sts-reports@google.com", "valid": true, "rua": [ "mailto:sts-reports@google.com" ], "errors": [] }, "resolver_latency": { "record_type": "MX", "resolvers": [ { "resolver": "1.1.1.1", "label": "Cloudflare", "query_ms": 22, "status": "NOERROR", "answer_count": 5, "answers": [ "aspmx.l.google.com" ], "server": "1.1.1.1#53", "error": null }, { "resolver": "8.8.8.8", "label": "Google Public DNS", "query_ms": 3, "status": "NOERROR", "answer_count": 5, "answers": [ "aspmx.l.google.com" ], "server": "8.8.8.8#53", "error": null } ], "min_ms": 3, "max_ms": 22, "avg_ms": 12.5 }, "zone_transfer": { "exposed": false, "nameservers": [ { "host": "ns1.google.com", "exposed": false, "query_ms": 18, "records_returned": 0, "soa_seen": false, "reason": "transfer failed", "sample_records": [] } ] }, "blacklist": { "domain": "google.com", "listed": false, "threat_level": "none", "check_type": "domain", "checked_at": "2026-04-18T21:00:00Z" }, "edge_summary": { "relay_configured": true, "evidence_sources": [ "dnssec_validate", "axfr_check", "dns_authority_health", "dns_latency", "issuance_readiness", "mail_policies", "bimi_audit", "spf_walk" ], "secure_dns_chain": true, "zone_transfer_exposed": false, "authoritative_consistency_ok": true, "nameserver_drift_detected": false, "lame_nameserver_count": 0, "tcp_fallback_ready": null, "avg_resolver_latency_ms": 12.5, "fastest_resolver": "Google Public DNS", "slowest_resolver": "Cloudflare", "issuance_http01_ready": true, "caa_restricts_issuers": true, "bimi_vmc_valid": true, "mta_sts_enforced": true, "tls_rpt_configured": true, "spf_lookup_limit_exceeded": false }, "recommendations": [], "checked_at": "2026-04-18T21:00:00Z", "check_duration_ms": 312 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/dns-propagation # DNS Resolver Comparison API Compare answers from the Cloudflare and Google public recursive resolvers. These are two global-anycast DoH providers, not geographic probes or authoritative nameservers. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/dns-propagation) ## Operations GET `/v1/dns/propagation` [View API reference](https://domscan.net/docs/products/dns-propagation#getDnsPropagation) POST `/v1/dns/propagation/bulk` [View API reference](https://domscan.net/docs/products/dns-propagation#bulkDnsPropagation) GET `/v1/dns/servers` [View API reference](https://domscan.net/docs/products/dns-propagation#getDnsServers) ## GET `/v1/dns/propagation` Operation: `getDnsPropagation` Credits and authentication: 2 Authentication required GET /v1/dns/propagation Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | type | string Allowed values `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SOA` Default `A` | optional | | expected | string | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `record_type` | string | | `expected_value` | string \| null | | `measurement_scope` | string | | `percentage_basis` | string | | `propagation_percentage` | number | | `fully_propagated` | boolean | | `consistent` | boolean | | `unique_values[]` | string[] | | `results[]` | object[] | | `results[]` | object | | `results[].server` | object | | `results[].server.name` | string | | `results[].server.ip` | string | | `results[].server.provider` | string | | `results[].server.location` | string | | `results[].server.country` | string | | `results[].server.scope` | string | | `results[].server.doh_endpoint` | string | | `results[].server.documentation_url` | string | | `results[].server.format` | string | | `results[].success` | boolean | | `results[].records[]` | string[] | | `results[].ttl` | integer \| null | | `results[].response_time_ms` | integer | | `results[].error` | string \| null | | `checked_at` | string | | `total_duration_ms` | integer | | `summary` | object | | `summary.total_servers` | integer | | `summary.successful` | integer | | `summary.failed` | integer | | `summary.matching_expected` | integer | | `propagation_summary` | object | | `propagation_summary.measurement_scope` | string | | `propagation_summary.percentage_basis` | string | | `propagation_summary.resolver_count` | integer | | `propagation_summary.successful_count` | integer | | `propagation_summary.failed_count` | integer | | `propagation_summary.propagation_percentage` | number | | `propagation_summary.fully_propagated` | boolean | | `propagation_summary.consistent` | boolean | | `propagation_summary.unique_value_count` | integer | | `propagation_summary.matching_expected_count` | integer | | `propagation_summary.expected_value_present` | boolean \| null | | `propagation_summary.countries_checked` | integer | | `propagation_summary.providers_checked` | integer | | `propagation_summary.locations_checked` | integer | | `propagation_summary.slowest_resolver` | string \| null | | `propagation_summary.slowest_response_ms` | integer \| null | | `propagation_summary.fastest_response_ms` | integer \| null | | `propagation_summary.disagreement_count` | integer | | `propagation_summary.confidence` | string | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns/propagation?domain=example.com&type=A&expected=192.0.2.1" ``` ```javascript const response = await fetch("https://domscan.net/v1/dns/propagation?domain=example.com&type=A&expected=192.0.2.1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/dns/propagation?domain=example.com&type=A&expected=192.0.2.1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/dns/propagation?domain=example.com&type=A&expected=192.0.2.1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns/propagation?domain=example.com&type=A&expected=192.0.2.1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "record_type": "A", "expected_value": "192.0.2.10", "measurement_scope": "configured_recursive_resolvers", "percentage_basis": "expected_value_match", "propagation_percentage": 100, "fully_propagated": true, "consistent": true, "unique_values": [ "192.0.2.10" ], "results": [ { "server": { "name": "Cloudflare 1.1.1.1", "ip": "1.1.1.1", "location": "Global anycast", "country": "GLOBAL", "provider": "Cloudflare", "scope": "global-anycast", "doh_endpoint": "https://cloudflare-dns.com/dns-query", "documentation_url": "https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-json/", "format": "dns-json" }, "success": true, "records": [ "192.0.2.10" ], "ttl": 300, "response_time_ms": 38 }, { "server": { "name": "Google Public DNS", "ip": "8.8.8.8", "location": "Global anycast", "country": "GLOBAL", "provider": "Google", "scope": "global-anycast", "doh_endpoint": "https://dns.google/resolve", "documentation_url": "https://developers.google.com/speed/public-dns/docs/doh/json", "format": "dns-json" }, "success": true, "records": [ "192.0.2.10" ], "ttl": 300, "response_time_ms": 52 } ], "checked_at": "2026-10-09T10:15:30.000Z", "total_duration_ms": 61, "summary": { "total_servers": 2, "successful": 2, "failed": 0, "matching_expected": 2 }, "propagation_summary": { "measurement_scope": "configured_recursive_resolvers", "percentage_basis": "expected_value_match", "resolver_count": 2, "successful_count": 2, "failed_count": 0, "propagation_percentage": 100, "fully_propagated": true, "consistent": true, "unique_value_count": 1, "matching_expected_count": 2, "expected_value_present": true, "countries_checked": 1, "providers_checked": 2, "locations_checked": 1, "slowest_resolver": "Google Public DNS", "slowest_response_ms": 52, "fastest_response_ms": 38, "disagreement_count": 0, "confidence": "high" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/dns/propagation/bulk` Operation: `bulkDnsPropagation` Credits and authentication: 2 Authentication required POST /v1/dns/propagation/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | | type | string Allowed values `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SOA` Default `A` | optional | | expected | string | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/dns/propagation/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "cloudflare.com" ], "type": "A" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/dns/propagation/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "cloudflare.com" ], "type": "A" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/dns/propagation/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "cloudflare.com", ], "type": "A", }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "cloudflare.com" ], "type": "A" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/dns/propagation/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns/propagation/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "cloudflare.com" ], "type" => "A" }) #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/dns/servers` Operation: `getDnsServers` Credits and authentication: Free Authentication required GET /v1/dns/servers Credits: 0 #### Response fields | Field | Type | | --- | --- | | `measurement_scope` | string | | `geographic_vantage` | boolean | | `servers[]` | object[] | | `servers[]` | object | | `servers[].name` | string | | `servers[].location` | string | | `servers[].country` | string | | `servers[].ip` | string | | `servers[].provider` | string | | `servers[].scope` | string | | `servers[].doh_endpoint` | string | | `servers[].documentation_url` | string | | `servers[].format` | string | | `total` | integer | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/dns/servers" ``` ```javascript const response = await fetch("https://domscan.net/v1/dns/servers", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/dns/servers", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/dns/servers", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/dns/servers") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "servers": [ { "name": "Cloudflare 1.1.1.1", "ip": "1.1.1.1", "location": "Global anycast", "country": "GLOBAL", "provider": "Cloudflare", "scope": "global-anycast", "doh_endpoint": "https://cloudflare-dns.com/dns-query", "documentation_url": "https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-json/", "format": "dns-json" }, { "name": "Google Public DNS", "ip": "8.8.8.8", "location": "Global anycast", "country": "GLOBAL", "provider": "Google", "scope": "global-anycast", "doh_endpoint": "https://dns.google/resolve", "documentation_url": "https://developers.google.com/speed/public-dns/docs/doh/json", "format": "dns-json" } ], "total": 2, "measurement_scope": "configured_recursive_resolvers", "geographic_vantage": false } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/subdomains # Subdomain Finder API Discover subdomains for a domain using various enumeration techniques. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/subdomain-finder-api) ## Operations GET `/v1/subdomains` [View API reference](https://domscan.net/docs/products/subdomains#getSubdomains) POST `/v1/subdomains/bulk` [View API reference](https://domscan.net/docs/products/subdomains#bulkGetSubdomains) ## GET `/v1/subdomains` Operation: `getSubdomains` Credits and authentication: 4-5 Authentication required GET /v1/subdomains Credits: 4-5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | sources | string Allowed values `ct` Default `ct` | optional | | verify | string Allowed values `true`, `false`, `1`, `0`, `yes`, `no` Default `false` | optional | | include_wildcards | string Allowed values `true`, `false`, `1`, `0`, `yes`, `no` Default `false` | optional | | limit | integer Default `500` | optional | | prefer_cache | string Allowed values `true`, `false`, `1`, `0`, `yes`, `no` Default `false` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `cache_age_s` | integer | | `domain` | string | | `subdomains[]` | object[] | | `subdomains[]` | object | | `subdomains[].name` | string | | `subdomains[].source` | string | | `subdomains[].first_seen` | string \| null | | `subdomains[].verified` | boolean | | `subdomains[].dns_records` | object | | `subdomains[].dns_records.A[]` | string[] | | `subdomains[].dns_records.CNAME` | string \| null | | `wildcards[]` | object[] | | `wildcards[]` | object | | `wildcards[].pattern` | string | | `wildcards[].source` | string | | `wildcards[].first_seen` | string \| null | | `summary` | object | | `summary.total_found` | integer | | `summary.returned` | integer | | `summary.verified_count` | integer | | `summary.unverified_count` | integer | | `summary.sources_used[]` | string[] | | `summary.apex_included` | boolean | | `summary.wildcard_suppressed_count` | integer | | `summary.wildcard_returned_count` | integer | | `intelligence_summary` | object | | `intelligence_summary.data_sources[]` | string[] | | `intelligence_summary.source_count` | integer | | `intelligence_summary.cache_status` | string | | `intelligence_summary.returned_count` | integer | | `intelligence_summary.total_found` | integer | | `intelligence_summary.truncated` | boolean | | `intelligence_summary.limit` | integer | | `intelligence_summary.verification_requested` | boolean | | `intelligence_summary.include_wildcards` | boolean | | `intelligence_summary.verified_count` | integer | | `intelligence_summary.verified_ratio` | number \| null | | `intelligence_summary.live_dns_record_count` | integer | | `intelligence_summary.apex_included` | boolean | | `intelligence_summary.wildcard_suppressed_count` | integer | | `intelligence_summary.wildcard_returned_count` | integer | | `intelligence_summary.first_seen_oldest` | string \| null | | `intelligence_summary.first_seen_newest` | string \| null | | `intelligence_summary.warning_count` | integer | | `warnings[]` | string[] | | `meta` | object | | `meta.query_time_ms` | integer | | `meta.cached` | boolean | | `meta.stale` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/subdomains?domain=example.com&sources=ct&verify=yes&include_wildcards=1&limit=500&prefer_cache=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/subdomains?domain=example.com&sources=ct&verify=yes&include_wildcards=1&limit=500&prefer_cache=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/subdomains?domain=example.com&sources=ct&verify=yes&include_wildcards=1&limit=500&prefer_cache=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/subdomains?domain=example.com&sources=ct&verify=yes&include_wildcards=1&limit=500&prefer_cache=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/subdomains?domain=example.com&sources=ct&verify=yes&include_wildcards=1&limit=500&prefer_cache=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "subdomains": [ { "name": "api.example.com", "source": "crtsh", "first_seen": "2025-01-15T00:00:00Z", "verified": true, "dns_records": { "A": [ "example" ], "CNAME": "example" } } ], "summary": { "total_found": 1, "returned": 1, "verified_count": 1, "unverified_count": 1, "sources_used": [ "ct" ], "apex_included": false, "wildcard_suppressed_count": 1, "wildcard_returned_count": 1 }, "intelligence_summary": { "data_sources": [ "ct" ], "source_count": 1, "cache_status": "live", "returned_count": 1, "total_found": 1, "truncated": false, "limit": 1, "verification_requested": false, "include_wildcards": false, "verified_count": 1, "verified_ratio": 0.5, "live_dns_record_count": 1, "apex_included": false, "wildcard_suppressed_count": 1, "wildcard_returned_count": 1, "first_seen_oldest": "example", "first_seen_newest": "example", "warning_count": 1 }, "meta": { "query_time_ms": 1, "cached": false, "stale": false }, "has_more": false, "next_cursor": "example", "cache_age_s": 1, "wildcards": [ { "pattern": "*.example.com", "source": "ct", "first_seen": "example" } ], "warnings": [ "example" ] } ``` #### HTTP status codes - `200` OK - `202` Accepted - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable - `504` Gateway Timeout ## POST `/v1/subdomains/bulk` Operation: `bulkGetSubdomains` Credits and authentication: 4-5 Authentication required POST /v1/subdomains/bulk Credits: 4-5/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | | verify | boolean Default `false` | optional | | include_wildcards | boolean Default `false` | optional | | limit | integer Default `500` | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/subdomains/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "cloudflare.com" ], "verify": false, "limit": 500 }' ``` ```javascript const response = await fetch("https://domscan.net/v1/subdomains/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "cloudflare.com" ], "verify": false, "limit": 500 }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/subdomains/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "cloudflare.com", ], "verify": False, "limit": 500, }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "cloudflare.com" ], "verify": false, "limit": 500 }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/subdomains/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/subdomains/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "cloudflare.com" ], "verify" => false, "limit" => 500 }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/ip-intelligence # IP Geolocation API Get geolocation data for an IP address including country, city, and ISP. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/ip-lookup-api) ## Operations GET `/v1/ip` [View API reference](https://domscan.net/docs/products/ip-intelligence#getIpInfo) ## GET `/v1/ip` Operation: `getIpInfo` Credits and authentication: 1 Authentication required GET /v1/ip Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | ip | string | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `ip` | string | | `domain` | string \| null | | `geolocation` | object | | `geolocation.country` | string \| null | | `geolocation.country_name` | string \| null | | `geolocation.region` | string \| null | | `geolocation.region_name` | string \| null | | `geolocation.city` | string \| null | | `geolocation.postal` | string \| null | | `geolocation.latitude` | number \| null | | `geolocation.longitude` | number \| null | | `geolocation.timezone` | string \| null | | `geolocation.precision` | string | | `network` | object | | `network.asn` | integer \| null | | `network.asn_name` | string \| null | | `network.asn_org` | string \| null | | `network.isp` | string \| null | | `network.connection_type` | string \| null | | `security` | object | | `security.is_proxy` | boolean | | `security.is_vpn` | boolean | | `security.is_tor` | boolean | | `security.is_tor_exit` | boolean | | `security.is_datacenter` | boolean | | `security.is_cloud` | boolean | | `security.cloud_provider` | string \| null | | `security.threat_score` | integer | | `security.is_vpn_suspected` | boolean | | `security.vpn_suspected_provider` | string \| null | | `security.type_classification` | object | | `security.type_classification.type` | string | | `security.type_classification.confidence` | string | | `security.fcrdns` | object | | `security.fcrdns.ptr` | string \| null | | `security.fcrdns.fcrdns_valid` | boolean \| null | | `intelligence_summary` | object | | `intelligence_summary.query_type` | string | | `intelligence_summary.domain_resolved` | boolean | | `intelligence_summary.cache_status` | string | | `intelligence_summary.data_source` | string | | `intelligence_summary.confidence` | string | | `intelligence_summary.confidence_score` | integer | | `intelligence_summary.asn_present` | boolean | | `intelligence_summary.organization_present` | boolean | | `intelligence_summary.country_present` | boolean | | `intelligence_summary.security_signal_count` | integer | | `intelligence_summary.risk_flags[]` | string[] | | `intelligence_summary.hosting_category` | string | | `meta` | object | | `meta.query_time_ms` | integer | | `meta.cached` | boolean | | `meta.source` | string | | `meta.data_updated_at` | string \| null | | `meta.attribution` | object | | `meta.attribution.name` | string | | `meta.attribution.url` | string | | `meta.attribution.license` | string | | `meta.attribution.license_url` | string | | `meta.attribution.modified` | boolean | | `meta.warning_code` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ip?ip=8.8.8.8&domain=status.openai.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/ip?ip=8.8.8.8&domain=status.openai.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ip?ip=8.8.8.8&domain=status.openai.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ip?ip=8.8.8.8&domain=status.openai.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ip?ip=8.8.8.8&domain=status.openai.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "ip": "8.8.8.8", "domain": null, "geolocation": { "country": "US", "country_name": "United States", "region": null, "region_name": "California", "city": "Mountain View", "postal": null, "latitude": 37.422, "longitude": -122.085, "timezone": null, "precision": "city" }, "network": { "asn": 15169, "asn_name": "AS15169", "asn_org": "Google LLC", "isp": null, "connection_type": "hosting" }, "security": { "is_proxy": false, "is_vpn": false, "is_tor": false, "is_tor_exit": false, "is_datacenter": true, "is_cloud": true, "cloud_provider": "Google Cloud", "threat_score": 0, "type_classification": { "type": "datacenter", "confidence": "high" }, "fcrdns": { "ptr": "dns.google", "fcrdns_valid": true } }, "intelligence_summary": { "query_type": "ip", "domain_resolved": false, "cache_status": "miss", "data_source": "db-ip-lite+enrichment", "confidence": "high", "confidence_score": 100, "asn_present": true, "organization_present": true, "country_present": true, "security_signal_count": 2, "risk_flags": [ "cloud", "datacenter" ], "hosting_category": "cloud" }, "meta": { "query_time_ms": 118, "cached": false, "source": "db-ip-lite+enrichment", "data_updated_at": "2026-08-01T01:42:04.000Z", "attribution": { "name": "DB-IP Lite", "url": "https://db-ip.com", "license": "CC BY 4.0", "license_url": "https://creativecommons.org/licenses/by/4.0/", "modified": true } } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable - `504` Gateway Timeout ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/mac-lookup # MAC Address Lookup API Look up manufacturer information for a MAC address. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/mac-address-lookup-api) ## Operations GET `/v1/mac` [View API reference](https://domscan.net/docs/products/mac-lookup#getMacInfo) GET `/v1/mac/info` [View API reference](https://domscan.net/docs/products/mac-lookup#getMacLookupInfo) ## GET `/v1/mac` Operation: `getMacInfo` Credits and authentication: 1 Authentication required GET /v1/mac Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | mac | string | required | #### Response fields | Field | Type | | --- | --- | | `mac` | string | | `input` | string | | `type` | string | | `oui` | string | | `device_id` | string | | `flags` | object | | `flags.multicast` | boolean | | `flags.locally_administered` | boolean | | `flags.broadcast` | boolean | | `vendor` | object | | `vendor.name` | string \| null | | `vendor.found` | boolean | | `vendor.organization` | string \| null | | `vendor.address` | string \| null | | `vendor.country` | string \| null | | `vendor.device_type` | string \| null | | `vendor.source` | string | | `vendor.cached` | boolean | | `vendor.cache_age_s` | integer \| null | | `vendor.checked_at` | string | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/mac?mac=00%3A1A%3A2B%3A3C%3A4D%3A5E" ``` ```javascript const response = await fetch("https://domscan.net/v1/mac?mac=00%3A1A%3A2B%3A3C%3A4D%3A5E", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/mac?mac=00%3A1A%3A2B%3A3C%3A4D%3A5E", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/mac?mac=00%3A1A%3A2B%3A3C%3A4D%3A5E", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/mac?mac=00%3A1A%3A2B%3A3C%3A4D%3A5E") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "mac": "00:1A:2B:3C:4D:5E", "input": "00:1A:2B:3C:4D:5E", "type": "eui-48", "oui": "00:1A:2B", "device_id": "3C:4D:5E", "flags": { "multicast": false, "locally_administered": false, "broadcast": false }, "vendor": { "name": "Ayecom Technology Co., Ltd.", "found": true, "source": "live", "cached": false, "checked_at": "2026-10-09T10:15:30.000Z" }, "meta": { "served_by": "pop=MAD country=ES", "latency_ms": 184 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable ## GET `/v1/mac/info` Operation: `getMacLookupInfo` Credits and authentication: Free Authentication required GET /v1/mac/info Credits: 0 #### Response fields | Field | Type | | --- | --- | | `endpoint` | string | | `description` | string | | `parameters` | object | | `example_request` | string | | `example_response` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/mac/info" ``` ```javascript const response = await fetch("https://domscan.net/v1/mac/info", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/mac/info", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/mac/info", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/mac/info") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "endpoint": "/v1/mac", "description": "Lookup MAC address metadata and vendor information.", "parameters": { "mac": { "type": "string", "required": true, "description": "MAC address string in any common format", "example": "44:38:39:ff:ef:57" } }, "example_request": "/v1/mac?mac=44:38:39:ff:ef:57", "example_response": { "mac": "44:38:39:FF:EF:57", "type": "eui-48", "oui": "44:38:39", "device_id": "FF:EF:57", "flags": { "multicast": false, "locally_administered": false, "broadcast": false }, "vendor": { "name": "Cumulus Networks, Inc", "found": true, "source": "cache", "cached": true } } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-similarity # Domain Similarity API Find domains similar to a given domain based on name patterns and keywords. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-similarity-api) ## Operations GET `/v1/similarity` [View API reference](https://domscan.net/docs/products/domain-similarity#getDomainSimilarity) ## GET `/v1/similarity` Operation: `getDomainSimilarity` Credits and authentication: 2 Authentication required GET /v1/similarity Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain1 | string | required | | domain2 | string | required | #### Response fields | Field | Type | | --- | --- | | `domain1` | string | | `domain2` | string | | `overall_similarity` | number | | `risk_level` | string | | `analysis` | object | | `analysis.levenshtein_distance` | integer | | `analysis.levenshtein_similarity` | number | | `analysis.jaro_winkler_similarity` | number | | `analysis.visual_similarity` | number | | `analysis.keyboard_distance` | number | | `analysis.common_prefix_length` | integer | | `analysis.common_suffix_length` | integer | | `matching_methods[]` | string[] | | `is_potential_typosquat` | boolean | | `checked_at` | string | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/similarity?domain1=example.com&domain2=example.org" ``` ```javascript const response = await fetch("https://domscan.net/v1/similarity?domain1=example.com&domain2=example.org", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/similarity?domain1=example.com&domain2=example.org", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/similarity?domain1=example.com&domain2=example.org", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/similarity?domain1=example.com&domain2=example.org") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain1": "example.com", "domain2": "exampel.com", "overall_similarity": 79, "risk_level": "medium", "analysis": { "levenshtein_distance": 2, "levenshtein_similarity": 71, "jaro_winkler_similarity": 97, "visual_similarity": 71, "keyboard_distance": 6.08, "common_prefix_length": 5, "common_suffix_length": 0 }, "matching_methods": [ "jaro-winkler", "common-prefix", "same-tld" ], "is_potential_typosquat": true, "checked_at": "2026-10-09T10:15:30.000Z", "meta": { "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/typosquatting # Typosquatting Detection API Detect typosquatting threats and similar domains that could be used for phishing or brand abuse. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/typosquatting-detection) ## Operations GET `/v1/typos` [View API reference](https://domscan.net/docs/products/typosquatting#getTyposquatting) GET `/v1/typos/threats` [View API reference](https://domscan.net/docs/products/typosquatting#analyzeTyposquattingThreats) GET `/v1/typos/report` [View API reference](https://domscan.net/docs/products/typosquatting#generateTyposquattingReport) GET `/v1/typos/quick` [View API reference](https://domscan.net/docs/products/typosquatting#quickTyposquattingCheck) ## GET `/v1/typos` Operation: `getTyposquatting` Credits and authentication: 2-3 Authentication required GET /v1/typos Credits: 2-3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | check_registered | boolean Default `false` | optional | | limit | integer Default `100` | optional | | include_tld_swap | boolean Default `true` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `name` | string | | `tld` | string | | `permutations_generated` | integer | | `permutations_checked` | integer | | `registered_typos[]` | object[] | | `registered_typos[]` | object | | `registered_typos[].classification` | object | | `registered_typos[].classification.status` | string | | `registered_typos[].classification.reason` | string | | `registered_typos[].classification.evidence` | object | | `registered_typos[].classification.evidence.source` | string | | `registered_typos[].classification.evidence.method` | string | | `registered_typos[].classification.evidence.observed_at` | string | | `registered_typos[].classification.evidence.detail` | string | | `registered_typos[].classification.checked_at` | string | | `registered_typos[].domain` | string | | `registered_typos[].name` | string | | `registered_typos[].tld` | string | | `registered_typos[].type` | string | | `registered_typos[].risk` | string | | `registered_typos[].description` | string | | `registered_typos[].registered` | boolean | | `registered_typos[].checked_at` | string | | `available_typos` | integer | | `unknown_typos` | integer | | `risk_summary` | object | | `risk_summary.critical` | integer | | `risk_summary.high` | integer | | `risk_summary.medium` | integer | | `risk_summary.low` | integer | | `threat_level` | string | | `family_summary` | object | | `family_summary.generated_by_type` | object | | `family_summary.generated_by_risk` | object | | `family_summary.registered_by_type` | object | | `family_summary.registered_by_risk` | object | | `family_summary.top_generated_family` | string \| null | | `family_summary.top_registered_family` | string \| null | | `family_summary.critical_or_high_generated_count` | integer | | `family_summary.critical_or_high_registered_count` | integer | | `family_summary.coverage_ratio` | number | | `family_summary.checked_count` | integer | | `family_summary.available_count` | integer | | `family_summary.unknown_count` | integer | | `family_summary.omitted_count` | integer | | `family_summary.include_tld_swap` | boolean | | `family_summary.requested_limit` | integer | | `checked_at` | string | | `check_duration_ms` | integer | | `meta` | object | | `meta.served_by` | string | | `meta.cached` | boolean | | `meta.query_time_ms` | integer | | `meta.registration_check_requested` | boolean | | `meta.registration_check_limit` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/typos?domain=google.com&check_registered=false&limit=25&include_tld_swap=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/typos?domain=google.com&check_registered=false&limit=25&include_tld_swap=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/typos?domain=google.com&check_registered=false&limit=25&include_tld_swap=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/typos?domain=google.com&check_registered=false&limit=25&include_tld_swap=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/typos?domain=google.com&check_registered=false&limit=25&include_tld_swap=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "google.com", "name": "google", "tld": "com", "permutations_generated": 100, "permutations_checked": 95, "registered_typos": [ { "domain": "gooogle.com", "name": "gooogle", "tld": "com", "type": "repetition", "risk": "high", "description": "Repeated character", "registered": true }, { "domain": "gogle.com", "name": "gogle", "tld": "com", "type": "omission", "risk": "critical", "description": "Missing character", "registered": true } ], "available_typos": 50, "risk_summary": { "critical": 2, "high": 5, "medium": 10, "low": 28 }, "threat_level": "high", "checked_at": "2024-01-15T12:00:00Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/typos/threats` Operation: `analyzeTyposquattingThreats` Credits and authentication: 12 Authentication required GET /v1/typos/threats Credits: 12 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | limit | integer Default `200` | optional | | include_tld_swap | boolean Default `true` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `name` | string | | `tld` | string | | `scan_summary` | object | | `scan_summary.permutations_generated` | integer | | `scan_summary.permutations_checked` | integer | | `scan_summary.permutations_submitted` | integer | | `scan_summary.definitive_results` | integer | | `scan_summary.unknown_results` | integer | | `scan_summary.omitted_results` | integer | | `scan_summary.registered_count` | integer | | `scan_summary.active_threats` | integer | | `scan_summary.available_for_defensive` | integer | | `scan_summary.check_limit` | integer | | `scan_summary.coverage_truncated` | boolean | | `threat_level` | string | | `protection_score` | object | | `protection_score.score` | integer | | `protection_score.grade` | string | | `protection_score.interpretation` | object | | `protection_score.interpretation.score_meaning` | string | | `protection_score.interpretation.factors` | string | | `protection_score.interpretation.note` | string | | `protection_score.vulnerabilities[]` | object[] | | `protection_score.vulnerabilities[]` | object | | `protection_score.vulnerabilities[].category` | string | | `protection_score.vulnerabilities[].count` | integer | | `protection_score.vulnerabilities[].risk` | string | | `protection_score.vulnerabilities[].description` | string | | `protection_score.recommendations[]` | string[] | | `protection_score.factors` | object | | `protection_score.factors.length_factor` | integer | | `protection_score.factors.homoglyph_factor` | integer | | `protection_score.factors.keyboard_factor` | integer | | `protection_score.factors.tld_factor` | integer | | `threats[]` | object[] | | `threats[]` | object | | `threats[].classification` | object | | `threats[].classification.status` | string | | `threats[].classification.reason` | string | | `threats[].classification.evidence` | object | | `threats[].classification.evidence.source` | string | | `threats[].classification.evidence.method` | string | | `threats[].classification.evidence.observed_at` | string | | `threats[].classification.evidence.detail` | string | | `threats[].classification.checked_at` | string | | `threats[].domain` | string | | `threats[].name` | string | | `threats[].tld` | string | | `threats[].type` | string | | `threats[].risk` | string | | `threats[].description` | string | | `threats[].registered` | boolean | | `threats[].checked_at` | string | | `threats[].dns_active` | boolean | | `threats[].has_website` | boolean | | `threats[].has_mx` | boolean | | `threats[].infrastructure` | object | | `threats[].threat_indicators[]` | string[] | | `threats[].threat_score` | integer | | `defensive_opportunities[]` | object[] | | `defensive_opportunities[]` | object | | `defensive_opportunities[].domain` | string | | `defensive_opportunities[].name` | string | | `defensive_opportunities[].tld` | string | | `defensive_opportunities[].type` | string | | `defensive_opportunities[].risk` | string | | `defensive_opportunities[].description` | string | | `risk_breakdown` | object | | `recommendations[]` | string[] | | `checked_at` | string | | `scan_duration_ms` | integer | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/typos/threats?domain=example.com&limit=25&include_tld_swap=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/typos/threats?domain=example.com&limit=25&include_tld_swap=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/typos/threats?domain=example.com&limit=25&include_tld_swap=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/typos/threats?domain=example.com&limit=25&include_tld_swap=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/typos/threats?domain=example.com&limit=25&include_tld_swap=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "name": "example", "tld": "com", "scan_summary": { "permutations_generated": 109, "permutations_checked": 75, "permutations_submitted": 75, "definitive_results": 71, "unknown_results": 4, "omitted_results": 0, "registered_count": 2, "active_threats": 2, "available_for_defensive": 69, "check_limit": 75, "coverage_truncated": true }, "threat_level": "high", "protection_score": { "score": 2, "grade": "F", "interpretation": { "score_meaning": "Higher score = less vulnerable to typosquatting attacks", "factors": "Domain length, homoglyph-susceptible characters, keyboard adjacency, TLD popularity, registered typosquats", "note": "Short, well-known domains score lower because they have a larger inherent attack surface for typosquatting, not because they lack brand protection measures." }, "vulnerabilities": [ { "category": "homoglyph", "count": 4, "risk": "critical", "description": "Contains 4 characters with visual lookalikes (e, a, l)" }, { "category": "keyboard", "count": 5, "risk": "high", "description": "5 characters have many keyboard neighbors" }, { "category": "tld", "count": 1, "risk": "medium", "description": ".com is a high-value TLD commonly targeted by typosquatters" }, { "category": "registered_high", "count": 1, "risk": "high", "description": "1 high-risk typosquat domains are registered" } ], "recommendations": [ "Consider defensive registrations for common homoglyph variants", "Consider registering example on alternative TLDs like .net, .org" ], "factors": { "length_factor": 90, "homoglyph_factor": 68, "keyboard_factor": 75, "tld_factor": 80 } }, "threats": [ { "domain": "xeample.com", "type": "transposition", "risk": "high", "description": "Swapped 'e' and 'x'", "dns_active": true, "has_website": true, "has_mx": false, "infrastructure": { "nameservers": [] }, "threat_indicators": [ "Active DNS configuration", "Domain resolves to IP (potential website)" ], "threat_score": 75 }, { "domain": "example.net", "type": "tld-swap", "risk": "medium", "description": "TLD changed from .com to .net", "dns_active": true, "has_website": false, "has_mx": false, "infrastructure": { "nameservers": [] }, "threat_indicators": [ "Active DNS configuration" ], "threat_score": 40 } ], "defensive_opportunities": [ { "domain": "3xample.com", "type": "homoglyph", "risk": "critical" }, { "domain": "ex4mple.com", "type": "homoglyph", "risk": "critical" }, { "domain": "eaxmple.com", "type": "transposition", "risk": "high" } ], "risk_breakdown": { "critical": [], "high": [ { "domain": "xeample.com", "name": "xeample", "tld": "com", "type": "transposition", "risk": "high", "description": "Swapped 'e' and 'x'", "registered": true, "checked_at": "2026-10-09T10:15:29.000Z", "dns_active": true, "has_website": true, "has_mx": false, "infrastructure": { "nameservers": [] }, "threat_indicators": [ "Active DNS configuration", "Domain resolves to IP (potential website)" ], "threat_score": 75 } ], "medium": [ { "domain": "example.net", "name": "example", "tld": "net", "type": "tld-swap", "risk": "medium", "description": "TLD changed from .com to .net", "registered": true, "checked_at": "2026-10-09T10:15:29.000Z", "dns_active": true, "has_website": false, "has_mx": false, "infrastructure": { "nameservers": [] }, "threat_indicators": [ "Active DNS configuration" ], "threat_score": 40 } ], "low": [] }, "recommendations": [ "2 registered typosquat domains have active DNS/websites. Monitor for phishing or brand abuse.", "18 high-risk typosquat domains are available. Consider defensive registration to protect your brand.", "Your domain has significant typosquatting vulnerability. Set up continuous monitoring for new registrations." ], "checked_at": "2026-10-09T10:15:30.000Z", "scan_duration_ms": 4120, "meta": { "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `500` Server Error ## GET `/v1/typos/report` Operation: `generateTyposquattingReport` Credits and authentication: 18 Authentication required GET /v1/typos/report Credits: 18 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `generated_at` | string | | `executive_summary` | object | | `executive_summary.threat_level` | string | | `executive_summary.protection_grade` | string | | `executive_summary.active_threats` | integer | | `executive_summary.registered_typos` | integer | | `executive_summary.immediate_action_required` | boolean | | `threat_analysis` | object | | `threat_analysis.domain` | string | | `threat_analysis.name` | string | | `threat_analysis.tld` | string | | `threat_analysis.scan_summary` | object | | `threat_analysis.scan_summary.permutations_generated` | integer | | `threat_analysis.scan_summary.permutations_checked` | integer | | `threat_analysis.scan_summary.permutations_submitted` | integer | | `threat_analysis.scan_summary.definitive_results` | integer | | `threat_analysis.scan_summary.unknown_results` | integer | | `threat_analysis.scan_summary.omitted_results` | integer | | `threat_analysis.scan_summary.registered_count` | integer | | `threat_analysis.scan_summary.active_threats` | integer | | `threat_analysis.scan_summary.available_for_defensive` | integer | | `threat_analysis.scan_summary.check_limit` | integer | | `threat_analysis.scan_summary.coverage_truncated` | boolean | | `threat_analysis.threat_level` | string | | `threat_analysis.protection_score` | object | | `threat_analysis.protection_score.score` | integer | | `threat_analysis.protection_score.grade` | string | | `threat_analysis.protection_score.interpretation` | object | | `threat_analysis.protection_score.interpretation.score_meaning` | string | | `threat_analysis.protection_score.interpretation.factors` | string | | `threat_analysis.protection_score.interpretation.note` | string | | `threat_analysis.protection_score.vulnerabilities[]` | object[] | | `threat_analysis.protection_score.vulnerabilities[]` | object | | `threat_analysis.protection_score.vulnerabilities[].category` | string | | `threat_analysis.protection_score.vulnerabilities[].count` | integer | | `threat_analysis.protection_score.vulnerabilities[].risk` | string | | `threat_analysis.protection_score.vulnerabilities[].description` | string | | `threat_analysis.protection_score.recommendations[]` | string[] | | `threat_analysis.protection_score.factors` | object | | `threat_analysis.protection_score.factors.length_factor` | integer | | `threat_analysis.protection_score.factors.homoglyph_factor` | integer | | `threat_analysis.protection_score.factors.keyboard_factor` | integer | | `threat_analysis.protection_score.factors.tld_factor` | integer | | `threat_analysis.threats[]` | object[] | | `threat_analysis.threats[]` | object | | `threat_analysis.threats[].classification` | object | | `threat_analysis.threats[].classification.status` | string | | `threat_analysis.threats[].classification.reason` | string | | `threat_analysis.threats[].classification.evidence` | object | | `threat_analysis.threats[].classification.evidence.source` | string | | `threat_analysis.threats[].classification.evidence.method` | string | | `threat_analysis.threats[].classification.evidence.observed_at` | string | | `threat_analysis.threats[].classification.evidence.detail` | string | | `threat_analysis.threats[].classification.checked_at` | string | | `threat_analysis.threats[].domain` | string | | `threat_analysis.threats[].name` | string | | `threat_analysis.threats[].tld` | string | | `threat_analysis.threats[].type` | string | | `threat_analysis.threats[].risk` | string | | `threat_analysis.threats[].description` | string | | `threat_analysis.threats[].registered` | boolean | | `threat_analysis.threats[].checked_at` | string | | `threat_analysis.threats[].dns_active` | boolean | | `threat_analysis.threats[].has_website` | boolean | | `threat_analysis.threats[].has_mx` | boolean | | `threat_analysis.threats[].infrastructure` | object | | `threat_analysis.threats[].threat_indicators[]` | string[] | | `threat_analysis.threats[].threat_score` | integer | | `threat_analysis.defensive_opportunities[]` | object[] | | `threat_analysis.defensive_opportunities[]` | object | | `threat_analysis.defensive_opportunities[].domain` | string | | `threat_analysis.defensive_opportunities[].name` | string | | `threat_analysis.defensive_opportunities[].tld` | string | | `threat_analysis.defensive_opportunities[].type` | string | | `threat_analysis.defensive_opportunities[].risk` | string | | `threat_analysis.defensive_opportunities[].description` | string | | `threat_analysis.risk_breakdown` | object | | `threat_analysis.recommendations[]` | string[] | | `threat_analysis.checked_at` | string | | `threat_analysis.scan_duration_ms` | integer | | `threat_analysis.meta` | object | | `threat_analysis.meta.served_by` | string | | `defensive_registration_priority` | object | | `monitoring_recommendations[]` | string[] | | `estimated_risk_exposure` | string | | `meta` | object | | `meta.served_by` | string | | `meta.report_duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/typos/report?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/typos/report?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/typos/report?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/typos/report?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/typos/report?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "generated_at": "2026-08-27T12:00:00Z", "executive_summary": { "threat_level": "example", "protection_grade": "example", "active_threats": 1, "registered_typos": 1, "immediate_action_required": false }, "threat_analysis": { "domain": "example.com", "scan_summary": { "permutations_generated": 1, "permutations_checked": 1, "registered_count": 1, "active_threats": 1, "available_for_defensive": 1, "permutations_submitted": 1, "definitive_results": 1, "unknown_results": 1, "omitted_results": 1, "check_limit": 1, "coverage_truncated": false }, "threat_level": "none", "threats": [ { "domain": "example.com", "type": "domain", "risk": "critical", "dns_active": true, "has_website": false, "threat_indicators": [ "example" ], "threat_score": 85, "classification": { "status": "present", "evidence": { "source": "rdap", "method": "rdap_lookup", "observed_at": "2026-08-27T12:00:00Z", "detail": "example" }, "checked_at": "2026-08-27T12:00:00Z", "reason": "blocked" }, "name": "example", "tld": "com", "description": "example", "registered": false, "checked_at": "2026-08-27T12:00:00Z", "has_mx": false, "infrastructure": {} } ], "checked_at": "2026-08-27T12:00:00Z", "name": "example", "tld": "com", "protection_score": { "score": 85, "grade": "A", "interpretation": { "score_meaning": "example", "factors": "example", "note": "example" }, "vulnerabilities": [ { "category": "example", "count": 1, "risk": "critical", "description": "example" } ], "recommendations": [ "example" ], "factors": { "length_factor": 1, "homoglyph_factor": 1, "keyboard_factor": 1, "tld_factor": 1 } }, "defensive_opportunities": [ { "domain": "example.com", "name": "example", "tld": "com", "type": "omission", "risk": "critical", "description": "example" } ], "risk_breakdown": {}, "recommendations": [ "example" ], "scan_duration_ms": 1, "meta": { "served_by": "example" } }, "estimated_risk_exposure": "minimal", "defensive_registration_priority": {}, "monitoring_recommendations": [ "example" ], "meta": { "served_by": "example", "report_duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `500` Server Error ## GET `/v1/typos/quick` Operation: `quickTyposquattingCheck` Credits and authentication: 6 Authentication required GET /v1/typos/quick Credits: 6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | limit | integer Default `100` | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `registered_typos[]` | object[] | | `registered_typos[]` | object | | `registered_typos[].domain` | string | | `registered_typos[].type` | string | | `registered_typos[].risk` | string | | `registered_typos[].description` | string | | `registered_typos[].classification` | object | | `registered_typos[].classification.status` | string | | `registered_typos[].classification.reason` | string | | `registered_typos[].classification.evidence` | object | | `registered_typos[].classification.evidence.source` | string | | `registered_typos[].classification.evidence.method` | string | | `registered_typos[].classification.evidence.observed_at` | string | | `registered_typos[].classification.evidence.detail` | string | | `registered_typos[].classification.checked_at` | string | | `count` | integer | | `threat_level` | string | | `coverage` | object | | `coverage.requested` | integer | | `coverage.definitive` | integer | | `coverage.unknown` | integer | | `coverage.omitted` | integer | | `checked_at` | string | | `scan_duration_ms` | integer | | `meta` | object | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/typos/quick?domain=example.com&limit=25" ``` ```javascript const response = await fetch("https://domscan.net/v1/typos/quick?domain=example.com&limit=25", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/typos/quick?domain=example.com&limit=25", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/typos/quick?domain=example.com&limit=25", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/typos/quick?domain=example.com&limit=25") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "registered_typos": [ { "domain": "xeample.com", "type": "transposition", "risk": "high", "description": "Swapped 'e' and 'x'" }, { "domain": "example.net", "type": "tld-swap", "risk": "medium", "description": "TLD changed from .com to .net" } ], "count": 2, "threat_level": "high", "coverage": { "requested": 98, "definitive": 92, "unknown": 6, "omitted": 0 }, "checked_at": "2026-10-09T10:15:30.000Z", "scan_duration_ms": 2840, "meta": { "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `500` Server Error ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/idn-analysis # IDN and homograph analysis API API Convert punycode and Unicode domains and detect lookalike characters. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/idn-homograph-api) ## Operations GET `/v1/idn` [View API reference](https://domscan.net/docs/products/idn-analysis#getIdnAnalysis) ## GET `/v1/idn` Operation: `getIdnAnalysis` Credits and authentication: 1 Authentication required GET /v1/idn Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `input` | string | | `outcome` | string | | `unicode` | string | | `ascii` | string | | `is_idn` | boolean | | `valid` | boolean | | `errors[]` | string[] | | `labels[]` | object[] | | `labels[]` | object | | `labels[].unicode` | string | | `labels[].ascii` | string | | `labels[].is_idn` | boolean | | `labels[].scripts[]` | string[] | | `labels[].mixed_script` | boolean | | `labels[].has_invisible` | boolean | | `labels[].confusable_characters[]` | object[] | | `labels[].confusable_characters[]` | object | | `labels[].confusable_characters[].char` | string | | `labels[].confusable_characters[].codepoint` | string | | `labels[].confusable_characters[].script` | string | | `labels[].confusable_characters[].looks_like` | string | | `skeleton` | string | | `risk` | object | | `risk.level` | string | | `risk.reasons[]` | string[] | | `tld` | object | | `tld.label` | string | | `tld.ascii` | string | | `tld.is_idn` | boolean | | `checked_at` | string | | `caveats[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/idn?domain=xn--80ak6aa92e.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/idn?domain=xn--80ak6aa92e.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/idn?domain=xn--80ak6aa92e.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/idn?domain=xn--80ak6aa92e.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/idn?domain=xn--80ak6aa92e.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "input": "xn--80ak6aa92e.com", "outcome": "analyzed", "unicode": "аррӏе.com", "ascii": "xn--80ak6aa92e.com", "is_idn": true, "valid": true, "errors": [], "labels": [ { "unicode": "аррӏе", "ascii": "xn--80ak6aa92e", "is_idn": true, "scripts": [ "Cyrillic" ], "mixed_script": false, "has_invisible": false, "confusable_characters": [ { "char": "а", "codepoint": "U+0430", "script": "Cyrillic", "looks_like": "a" }, { "char": "р", "codepoint": "U+0440", "script": "Cyrillic", "looks_like": "p" }, { "char": "р", "codepoint": "U+0440", "script": "Cyrillic", "looks_like": "p" }, { "char": "ӏ", "codepoint": "U+04CF", "script": "Cyrillic", "looks_like": "l" }, { "char": "е", "codepoint": "U+0435", "script": "Cyrillic", "looks_like": "e" } ] }, { "unicode": "com", "ascii": "com", "is_idn": false, "scripts": [ "Latin" ], "mixed_script": false, "has_invisible": false, "confusable_characters": [] } ], "skeleton": "apple.com", "risk": { "level": "high", "reasons": [ "whole_script_confusable", "idn_label" ] }, "tld": { "label": "com", "ascii": "com", "is_idn": false }, "checked_at": "2026-10-09T10:15:30.000Z", "caveats": [ "partial_confusable_table" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/certificate-intelligence # SSL Certificates API Get SSL certificate information including issuer, validity, and security grade. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/certificate-transparency-api) ## Operations GET `/v1/certificates` [View API reference](https://domscan.net/docs/products/certificate-intelligence#getCertificates) POST `/v1/certificates/bulk` [View API reference](https://domscan.net/docs/products/certificate-intelligence#bulkGetCertificates) GET `/v1/ssl/audit` [View API reference](https://domscan.net/docs/products/certificate-intelligence#getSslAudit)[Read the guide](https://domscan.net/ssl-audit-api) GET `/v1/ssl/deep-scan` [View API reference](https://domscan.net/docs/products/certificate-intelligence#getSslDeepScan)[Read the guide](https://domscan.net/ssl-deep-scan-api) GET `/v1/ssl/grade` [View API reference](https://domscan.net/docs/products/certificate-intelligence#getSslGrade)[Read the guide](https://domscan.net/ssl-grade-api) GET `/v1/ssl/chain` [View API reference](https://domscan.net/docs/products/certificate-intelligence#getSslChain)[Read the guide](https://domscan.net/ssl-chain-api) GET `/v1/ssl/expiring` [View API reference](https://domscan.net/docs/products/certificate-intelligence#getSslExpiring)[Read the guide](https://domscan.net/ssl-expiry-check-api) ## GET `/v1/certificates` Operation: `getCertificates` Credits and authentication: 2 Authentication required GET /v1/certificates Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | include_subdomains | boolean Default `true` | optional | | include_expired | boolean Default `false` | optional | | limit | integer Default `100` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `cache_age_s` | integer | | `domain` | string | | `certificates[]` | object[] | | `certificates[]` | object | | `certificates[].id` | string | | `certificates[].issuer` | object | | `certificates[].common_name` | string | | `certificates[].san[]` | string[] | | `certificates[].not_before` | string | | `certificates[].not_after` | string | | `certificates[].is_expired` | boolean | | `certificates[].is_wildcard` | boolean | | `certificates[].fingerprint_sha256` | string | | `summary` | object | | `summary.total_found` | integer | | `summary.returned` | integer | | `summary.unique_subdomains` | integer | | `summary.issuers[]` | string[] | | `summary.earliest_cert` | string \| null | | `summary.latest_cert` | string \| null | | `pagination` | object | | `pagination.limit` | integer | | `pagination.offset` | integer | | `pagination.returned` | integer | | `pagination.total` | integer | | `pagination.has_more` | boolean | | `pagination.next_cursor` | string \| null | | `intelligence_summary` | object | | `intelligence_summary.data_source` | string | | `intelligence_summary.ct_log_sources[]` | string[] | | `intelligence_summary.source_count` | integer | | `intelligence_summary.cache_status` | string | | `intelligence_summary.returned_count` | integer | | `intelligence_summary.total_found` | integer | | `intelligence_summary.truncated` | boolean | | `intelligence_summary.limit` | integer | | `intelligence_summary.include_subdomains` | boolean | | `intelligence_summary.include_expired` | boolean | | `intelligence_summary.unique_name_count` | integer | | `intelligence_summary.unique_subdomains` | integer | | `intelligence_summary.issuer_count` | integer | | `intelligence_summary.wildcard_cert_count` | integer | | `intelligence_summary.active_cert_count` | integer | | `intelligence_summary.expired_cert_count` | integer | | `intelligence_summary.expiring_within_30_days_count` | integer | | `intelligence_summary.earliest_cert` | string \| null | | `intelligence_summary.latest_cert` | string \| null | | `intelligence_summary.latest_expiry` | string \| null | | `intelligence_summary.has_more` | boolean | | `intelligence_summary.next_cursor` | string \| null | | `intelligence_summary.warning_code` | string \| null | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/certificates?domain=example.com&include_subdomains=true&include_expired=false&limit=25&cursor=example" ``` ```javascript const response = await fetch("https://domscan.net/v1/certificates?domain=example.com&include_subdomains=true&include_expired=false&limit=25&cursor=example", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/certificates?domain=example.com&include_subdomains=true&include_expired=false&limit=25&cursor=example", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/certificates?domain=example.com&include_subdomains=true&include_expired=false&limit=25&cursor=example", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/certificates?domain=example.com&include_subdomains=true&include_expired=false&limit=25&cursor=example") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "certificates": [ { "id": "16234550871", "issuer": { "name": "R11", "organization": "Let's Encrypt" }, "common_name": "www.example.com", "san": [ "example.com", "www.example.com" ], "not_before": "2026-09-14T08:12:44", "not_after": "2026-12-13T08:12:43", "is_expired": false, "is_wildcard": false }, { "id": "16198877412", "issuer": { "name": "R11", "organization": "Let's Encrypt" }, "common_name": "api.example.com", "san": [ "api.example.com" ], "not_before": "2026-08-20T14:03:10", "not_after": "2026-11-18T14:03:09", "is_expired": false, "is_wildcard": false } ], "summary": { "total_found": 14, "returned": 2, "unique_subdomains": 3, "issuers": [ "Let's Encrypt" ], "earliest_cert": "2026-08-20T14:03:10", "latest_cert": "2026-09-14T08:12:44" }, "pagination": { "limit": 2, "offset": 0, "returned": 2, "total": 14, "has_more": true, "next_cursor": "2" }, "intelligence_summary": { "data_source": "crt.sh", "ct_log_sources": [ "crt.sh" ], "source_count": 1, "cache_status": "live", "returned_count": 2, "total_found": 14, "truncated": true, "limit": 2, "include_subdomains": true, "include_expired": false, "unique_name_count": 3, "unique_subdomains": 3, "issuer_count": 1, "wildcard_cert_count": 0, "active_cert_count": 2, "expired_cert_count": 0, "expiring_within_30_days_count": 0, "earliest_cert": "2026-08-20T14:03:10", "latest_cert": "2026-09-14T08:12:44", "latest_expiry": "2026-12-13T08:12:43", "has_more": true, "next_cursor": "2", "warning_code": null }, "meta": { "source": "crt.sh", "ct_log_sources": [ "crt.sh" ], "query_time_ms": 1240, "cached": false, "page": { "limit": 2, "offset": 0, "returned": 2, "total": 14, "has_more": true, "next_cursor": "2" }, "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable - `504` Gateway Timeout ## POST `/v1/certificates/bulk` Operation: `bulkGetCertificates` Credits and authentication: 2 Authentication required POST /v1/certificates/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | | include_subdomains | boolean Default `true` | optional | | include_expired | boolean Default `false` | optional | | limit | integer Default `100` | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/certificates/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "cloudflare.com" ], "include_subdomains": true, "limit": 100 }' ``` ```javascript const response = await fetch("https://domscan.net/v1/certificates/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "cloudflare.com" ], "include_subdomains": true, "limit": 100 }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/certificates/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "cloudflare.com", ], "include_subdomains": True, "limit": 100, }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "cloudflare.com" ], "include_subdomains": true, "limit": 100 }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/certificates/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/certificates/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "cloudflare.com" ], "include_subdomains" => true, "limit" => 100 }) #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/ssl/audit` Operation: `getSslAudit` Credits and authentication: 5 Authentication required GET /v1/ssl/audit Credits: 5 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `audit_completeness` | string | | `probe_coverage` | object | | `probe_coverage.tls_inspect` | boolean | | `probe_coverage.tls_audit` | boolean | | `probe_coverage.tls_posture` | boolean | | `probe_coverage.revocation` | boolean | | `probe_coverage.hsts` | boolean | | `probe_coverage.http_versions` | boolean | | `certificate` | object | | `certificate.subject` | string | | `certificate.issuer` | string | | `certificate.issuer_org` | string | | `certificate.valid_from` | string | | `certificate.valid_until` | string | | `certificate.days_remaining` | integer | | `certificate.expired` | boolean | | `certificate.san[]` | string[] | | `certificate.key_type` | string | | `certificate.key_size` | integer | | `certificate.signature_algorithm` | string | | `certificate.serial_number` | string | | `certificate.fingerprint_sha256` | string | | `certificate.hostname_match` | boolean \| null | | `chain` | object | | `chain.length` | integer | | `chain.valid` | boolean | | `chain.certificates[]` | object[] | | `chain.certificates[]` | object | | `chain.certificates[].subject` | string | | `chain.certificates[].issuer` | string | | `chain.certificates[].type` | string | | `chain.certificates[].valid_from` | string \| null | | `chain.certificates[].valid_until` | string \| null | | `chain.issues[]` | string[] | | `protocols` | object | | `protocols.tls_1_3` | boolean | | `protocols.tls_1_2` | boolean | | `protocols.tls_1_1` | boolean | | `protocols.tls_1_0` | boolean | | `protocols.ssl_3` | boolean | | `protocols.preferred_protocol` | string | | `protocols.detection_method` | string | | `protocols.deprecated_protocols_enabled` | boolean | | `connection` | object | | `connection.preferred_protocol` | string \| null | | `connection.preferred_cipher` | string \| null | | `connection.alpn_negotiated` | string \| null | | `connection.forward_secrecy` | boolean | | `connection.forward_secrecy_cipher` | string \| null | | `connection.secure_renegotiation_supported` | boolean \| null | | `connection.server_temp_key` | string \| null | | `connection.peer_signing_digest` | string \| null | | `connection.peer_signature_type` | string \| null | | `connection.server_public_key_bits` | integer \| null | | `connection.compression` | string \| null | | `connection.expansion` | string \| null | | `connection.client_certificate_requested` | boolean \| null | | `certificate_delivery` | object | | `certificate_delivery.must_staple` | boolean | | `certificate_delivery.sct_embedded` | boolean | | `certificate_delivery.sct_count` | integer | | `certificate_delivery.ocsp_stapling_present` | boolean | | `certificate_delivery.ocsp_stapling_fresh` | boolean \| null | | `certificate_delivery.ocsp_stapling_status` | string \| null | | `certificate_delivery.ocsp_this_update` | string \| null | | `certificate_delivery.ocsp_next_update` | string \| null | | `handshake_size` | object | | `handshake_size.chain_certificate_count` | integer | | `handshake_size.estimated_certificate_bytes` | integer | | `handshake_size.estimated_handshake_bytes` | integer | | `handshake_size.risk` | string | | `handshake_size.mobile_client_warning` | boolean | | `alpn_summary` | object | | `alpn_summary.negotiated_protocol` | string \| null | | `alpn_summary.http2_ready` | boolean \| null | | `alpn_summary.http3_advertised` | boolean \| null | | `alpn_summary.fallback_protocols[]` | string[] | | `alpn_summary.evidence_sources[]` | string[] | | `transport` | object | | `transport.hsts` | object | | `transport.hsts.reachable` | boolean | | `transport.hsts.final_url` | string \| null | | `transport.hsts.status_code` | integer \| null | | `transport.hsts.header_present` | boolean | | `transport.hsts.hsts_header` | string \| null | | `transport.hsts.max_age` | integer \| null | | `transport.hsts.include_subdomains` | boolean \| null | | `transport.hsts.preload_directive` | boolean \| null | | `transport.hsts.preload_eligible` | boolean | | `transport.hsts.preload_status` | string \| null | | `transport.hsts.preloaded_domain` | string \| null | | `transport.hsts.issues[]` | string[] | | `transport.hsts.errors[]` | string[] | | `transport.http_versions` | object | | `transport.http_versions.http1_1` | boolean | | `transport.http_versions.http2` | boolean | | `transport.http_versions.http3` | boolean | | `transport.http_versions.alt_svc` | string \| null | | `transport.http_versions.http3_advertised` | boolean | | `transport.http_versions.alt_svc_protocols[]` | string[] | | `transport.http_versions.curl_http3_supported` | boolean | | `revocation` | object | | `revocation.ocsp` | object | | `revocation.ocsp.present` | boolean | | `revocation.ocsp.uris[]` | string[] | | `revocation.ocsp.checked_uri` | string \| null | | `revocation.ocsp.status` | string \| null | | `revocation.ocsp.verify_ok` | boolean | | `revocation.ocsp.this_update` | string \| null | | `revocation.ocsp.next_update` | string \| null | | `revocation.ocsp.error` | string \| null | | `revocation.crl` | object | | `revocation.crl.present` | boolean | | `revocation.crl.uris[]` | string[] | | `revocation.crl.checked_uri` | string \| null | | `revocation.crl.fetched` | boolean | | `revocation.crl.http_status` | integer \| null | | `revocation.crl.revoked` | boolean \| null | | `revocation.crl.last_update` | string \| null | | `revocation.crl.next_update` | string \| null | | `revocation.crl.revoked_serial_count` | integer \| null | | `revocation.crl.error` | string \| null | | `tls_extensions[]` | string[] | | `edge_summary` | object | | `edge_summary.relay_configured` | boolean | | `edge_summary.evidence_sources[]` | string[] | | `edge_summary.probe_success_count` | integer | | `edge_summary.probe_attempt_count` | integer | | `edge_summary.live_handshake_ms` | integer \| null | | `edge_summary.strongest_protocol` | string \| null | | `edge_summary.weakest_supported_protocol` | string \| null | | `edge_summary.deprecated_protocol_count` | integer | | `edge_summary.http3_ready` | boolean | | `edge_summary.hsts_preload_ready` | boolean | | `edge_summary.revocation_checked` | boolean | | `edge_summary.revocation_good` | boolean \| null | | `edge_summary.certificate_transparency_ready` | boolean | | `edge_summary.client_auth_requested` | boolean \| null | | `edge_summary.weak_transport_detected` | boolean | | `issues[]` | string[] | | `recommendations[]` | string[] | | `checked_at` | string | | `check_duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ssl/audit?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/ssl/audit?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ssl/audit?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ssl/audit?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ssl/audit?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "cloudflare.com", "audit_completeness": "full", "probe_coverage": { "tls_inspect": true, "tls_audit": true, "tls_posture": true, "revocation": true, "hsts": true, "http_versions": true }, "certificate": { "subject": "cloudflare.com", "issuer": "Google Trust Services", "valid_from": "2026-03-01T00:00:00Z", "valid_until": "2026-05-30T23:59:59Z", "days_remaining": 42, "expired": false, "san": [ "cloudflare.com", "*.cloudflare.com" ], "key_type": "ECDSA", "key_size": 256, "signature_algorithm": "ecdsaWithSHA256", "serial_number": "539933F4CFE7E8CF13F5E60D139675A1", "fingerprint_sha256": "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99", "hostname_match": true }, "chain": { "length": 3, "valid": true, "certificates": [ { "subject": "cloudflare.com", "issuer": "Google Trust Services", "type": "leaf" }, { "subject": "Google Trust Services", "issuer": "GlobalSign", "type": "intermediate" }, { "subject": "GlobalSign", "issuer": "GlobalSign", "type": "root" } ], "issues": [] }, "protocols": { "tls_1_3": true, "tls_1_2": true, "tls_1_1": false, "tls_1_0": false, "ssl_3": false, "preferred_protocol": "TLSv1.3", "detection_method": "active", "deprecated_protocols_enabled": false }, "connection": { "preferred_protocol": "TLSv1.3", "preferred_cipher": "TLS_AES_256_GCM_SHA384", "alpn_negotiated": "h2", "forward_secrecy": true, "forward_secrecy_cipher": "TLS_AES_256_GCM_SHA384", "secure_renegotiation_supported": false, "server_temp_key": "X25519, 253 bits", "peer_signing_digest": "SHA256", "peer_signature_type": "ECDSA", "server_public_key_bits": 256, "compression": "NONE", "expansion": "NONE", "client_certificate_requested": false }, "certificate_delivery": { "must_staple": false, "sct_embedded": true, "sct_count": 2, "ocsp_stapling_present": true, "ocsp_stapling_fresh": true, "ocsp_stapling_status": "successful (0x0)", "ocsp_this_update": "2026-04-15T02:35:16Z", "ocsp_next_update": "2026-04-22T01:35:15Z" }, "handshake_size": { "chain_certificate_count": 3, "estimated_certificate_bytes": 3200, "estimated_handshake_bytes": 4600, "risk": "low", "mobile_client_warning": false }, "alpn_summary": { "negotiated_protocol": "h2", "http2_ready": true, "http3_advertised": true, "fallback_protocols": [ "TLSv1.3", "TLSv1.2", "http/1.1" ], "evidence_sources": [ "tls_audit", "http_versions" ] }, "transport": { "hsts": { "reachable": true, "final_url": "https://cloudflare.com/", "status_code": 200, "header_present": true, "hsts_header": "max-age=31536000; includeSubDomains", "max_age": 31536000, "include_subdomains": true, "preload_directive": false, "preload_eligible": true, "preload_status": "preloaded", "preloaded_domain": "cloudflare.com", "issues": [ "missing preload directive" ], "errors": [] }, "http_versions": { "http1_1": true, "http2": true, "http3": true, "alt_svc": "h3=\":443\"; ma=86400", "http3_advertised": true, "alt_svc_protocols": [ "h3" ], "curl_http3_supported": true } }, "revocation": { "ocsp": { "present": true, "uris": [ "http://o.pki.goog/wr2" ], "checked_uri": "http://o.pki.goog/wr2", "status": "good", "verify_ok": true, "this_update": "2026-04-18T20:30:00Z", "next_update": "2026-04-19T20:30:00Z", "error": null }, "crl": { "present": true, "uris": [ "http://c.pki.goog/wr2.crl" ], "checked_uri": "http://c.pki.goog/wr2.crl", "fetched": true, "http_status": 200, "revoked": false, "last_update": "2026-04-17T00:00:00Z", "next_update": "2026-04-24T00:00:00Z", "revoked_serial_count": 0, "error": null } }, "tls_extensions": [ "key share", "supported versions", "server name" ], "edge_summary": { "relay_configured": true, "evidence_sources": [ "tls_inspect", "tls_audit", "tls_posture", "revocation", "hsts", "http_versions" ], "probe_success_count": 6, "probe_attempt_count": 6, "live_handshake_ms": 51, "strongest_protocol": "TLSv1.3", "weakest_supported_protocol": "TLSv1.2", "deprecated_protocol_count": 0, "http3_ready": true, "hsts_preload_ready": true, "revocation_checked": true, "revocation_good": true, "certificate_transparency_ready": true, "client_auth_requested": false, "weak_transport_detected": false }, "issues": [], "recommendations": [ "Add the preload directive if you want HSTS preload-list eligibility." ], "checked_at": "2026-04-18T21:00:00Z", "check_duration_ms": 512 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/ssl/deep-scan` Operation: `getSslDeepScan` Credits and authentication: 10 Authentication required GET /v1/ssl/deep-scan Credits: 10 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | refresh | boolean Default `false` | optional | | profile | string Allowed values `standard`, `full` Default `standard` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `status` | string | | `domain` | string | | `host` | string | | `port` | integer | | `profile` | string | | `scan_token` | string | | `message` | string | | `poll_after_ms` | integer | | `cache` | object | | `cache.hit` | boolean | | `cache.fresh` | boolean | | `cache.started_at` | string \| null | | `cache.completed_at` | string \| null | | `cache.expires_at` | string \| null | | `cache.engine` | string \| null | | `cache.profile` | string \| null | | `result` | object | | `result.domain` | string | | `result.host` | string | | `result.port` | integer | | `result.engine` | object | | `result.engine.name` | string | | `result.engine.mode` | string | | `result.engine.version` | string \| null | | `result.engine.profile` | string | | `result.target` | object | | `result.target.ip` | string \| null | | `result.target.service` | string \| null | | `result.target.rdns` | string \| null | | `result.summary` | object | | `result.summary.severity_counts` | object | | `result.summary.severity_counts.critical` | integer | | `result.summary.severity_counts.high` | integer | | `result.summary.severity_counts.medium` | integer | | `result.summary.severity_counts.low` | integer | | `result.summary.severity_counts.warn` | integer | | `result.summary.severity_counts.info` | integer | | `result.summary.severity_counts.ok` | integer | | `result.summary.actionable_findings` | integer | | `result.summary.protocols_offered[]` | string[] | | `result.summary.deprecated_protocols[]` | string[] | | `result.summary.supports_tls_1_3` | boolean | | `result.summary.supports_http2` | boolean \| null | | `result.summary.supports_http3` | boolean \| null | | `result.sections` | object | | `result.sections.pretest[]` | object[] | | `result.sections.pretest[]` | object | | `result.sections.pretest[].id` | string | | `result.sections.pretest[].severity` | string | | `result.sections.pretest[].finding` | string | | `result.sections.pretest[].cve` | string | | `result.sections.pretest[].cwe` | string | | `result.sections.protocols[]` | object[] | | `result.sections.protocols[]` | object | | `result.sections.protocols[].id` | string | | `result.sections.protocols[].severity` | string | | `result.sections.protocols[].finding` | string | | `result.sections.protocols[].cve` | string | | `result.sections.protocols[].cwe` | string | | `result.sections.server_defaults[]` | object[] | | `result.sections.server_defaults[]` | object | | `result.sections.server_defaults[].id` | string | | `result.sections.server_defaults[].severity` | string | | `result.sections.server_defaults[].finding` | string | | `result.sections.server_defaults[].cve` | string | | `result.sections.server_defaults[].cwe` | string | | `result.sections.server_preferences[]` | object[] | | `result.sections.server_preferences[]` | object | | `result.sections.server_preferences[].id` | string | | `result.sections.server_preferences[].severity` | string | | `result.sections.server_preferences[].finding` | string | | `result.sections.server_preferences[].cve` | string | | `result.sections.server_preferences[].cwe` | string | | `result.sections.cipher_categories[]` | object[] | | `result.sections.cipher_categories[]` | object | | `result.sections.cipher_categories[].id` | string | | `result.sections.cipher_categories[].severity` | string | | `result.sections.cipher_categories[].finding` | string | | `result.sections.cipher_categories[].cve` | string | | `result.sections.cipher_categories[].cwe` | string | | `result.sections.forward_secrecy[]` | object[] | | `result.sections.forward_secrecy[]` | object | | `result.sections.forward_secrecy[].id` | string | | `result.sections.forward_secrecy[].severity` | string | | `result.sections.forward_secrecy[].finding` | string | | `result.sections.forward_secrecy[].cve` | string | | `result.sections.forward_secrecy[].cwe` | string | | `result.sections.vulnerabilities[]` | object[] | | `result.sections.vulnerabilities[]` | object | | `result.sections.vulnerabilities[].id` | string | | `result.sections.vulnerabilities[].severity` | string | | `result.sections.vulnerabilities[].finding` | string | | `result.sections.vulnerabilities[].cve` | string | | `result.sections.vulnerabilities[].cwe` | string | | `result.sections.browser_simulations[]` | object[] | | `result.sections.browser_simulations[]` | object | | `result.sections.browser_simulations[].id` | string | | `result.sections.browser_simulations[].severity` | string | | `result.sections.browser_simulations[].finding` | string | | `result.sections.browser_simulations[].cve` | string | | `result.sections.browser_simulations[].cwe` | string | | `result.sections.rating[]` | object[] | | `result.sections.rating[]` | object | | `result.sections.rating[].id` | string | | `result.sections.rating[].severity` | string | | `result.sections.rating[].finding` | string | | `result.sections.rating[].cve` | string | | `result.sections.rating[].cwe` | string | | `result.findings[]` | object[] | | `result.findings[]` | object | | `result.findings[].section` | string | | `result.findings[].id` | string | | `result.findings[].severity` | string | | `result.findings[].finding` | string | | `result.findings[].cve` | string | | `result.findings[].cwe` | string | | `result.checked_at` | string | | `result.scan_duration_ms` | integer | | `result.notes[]` | string[] | | `error` | object | | `error.message` | string | | `error.retryable` | boolean | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ssl/deep-scan?domain=openai.com&refresh=false&profile=standard" ``` ```javascript const response = await fetch("https://domscan.net/v1/ssl/deep-scan?domain=openai.com&refresh=false&profile=standard", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ssl/deep-scan?domain=openai.com&refresh=false&profile=standard", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ssl/deep-scan?domain=openai.com&refresh=false&profile=standard", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ssl/deep-scan?domain=openai.com&refresh=false&profile=standard") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "status": "ready", "domain": "openai.com", "host": "openai.com", "port": 443, "profile": "full", "scan_token": "eyJrIjoidGxzLWRlZXAtc2NhbiIsImkiOiJleGFtcGxlIiwiaCI6Im9wZW5haS5jb20ifQ", "cache": { "hit": true, "fresh": true, "completed_at": "2026-04-18T22:10:00Z", "expires_at": "2026-04-19T22:10:00Z", "engine": "testssl.sh", "profile": "full" }, "result": { "domain": "openai.com", "host": "openai.com", "port": 443, "engine": { "name": "testssl.sh", "mode": "testssl", "version": "3.3dev", "profile": "full" }, "target": { "ip": "172.64.154.211", "service": "HTTP", "rdns": "--" }, "summary": { "severity_counts": { "critical": 0, "high": 1, "medium": 1, "low": 0, "warn": 1, "info": 6, "ok": 4 }, "actionable_findings": 3, "protocols_offered": [ "TLS1_2", "TLS1_3" ], "deprecated_protocols": [], "supports_tls_1_3": true, "supports_http2": true, "supports_http3": null }, "sections": { "pretest": [], "protocols": [ { "id": "TLS1_2", "severity": "OK", "finding": "offered" }, { "id": "TLS1_3", "severity": "OK", "finding": "offered with final" }, { "id": "QUIC", "severity": "WARN", "finding": "not tested due to lack of local OpenSSL support" } ], "server_defaults": [ { "id": "early_data", "severity": "HIGH", "finding": "supported" } ], "server_preferences": [], "cipher_categories": [], "forward_secrecy": [], "vulnerabilities": [ { "id": "BREACH", "severity": "MEDIUM", "finding": "potentially VULNERABLE, br gzip HTTP compression detected", "cve": "CVE-2013-3587", "cwe": "CWE-310" } ], "browser_simulations": [], "rating": [] }, "findings": [ { "section": "protocols", "id": "QUIC", "severity": "WARN", "finding": "not tested due to lack of local OpenSSL support" }, { "section": "server_defaults", "id": "early_data", "severity": "HIGH", "finding": "supported" }, { "section": "vulnerabilities", "id": "BREACH", "severity": "MEDIUM", "finding": "potentially VULNERABLE, br gzip HTTP compression detected", "cve": "CVE-2013-3587", "cwe": "CWE-310" } ], "checked_at": "2026-04-18T22:10:00Z", "scan_duration_ms": 53880, "notes": [] } } ``` #### HTTP status codes - `200` OK - `202` Accepted - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `424` HTTP 424 - `429` Too Many Requests ## GET `/v1/ssl/grade` Operation: `getSslGrade` Credits and authentication: 3 Authentication required GET /v1/ssl/grade Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `grade` | string \| null | | `score` | integer \| null | | `grade_reason` | string \| null | | `protocol_support` | object | | `protocol_support.tls_1_3` | boolean | | `protocol_support.tls_1_2` | boolean | | `protocol_support.tls_1_1` | boolean | | `protocol_support.tls_1_0` | boolean | | `protocol_support.ssl_3` | boolean | | `protocol_support.preferred_protocol` | string | | `protocol_support.detection_method` | string | | `certificate` | object | | `certificate.subject` | string | | `certificate.issuer` | string | | `certificate.issuer_org` | string | | `certificate.valid_from` | string | | `certificate.valid_until` | string | | `certificate.days_remaining` | integer | | `certificate.expired` | boolean | | `certificate.san[]` | string[] | | `certificate.key_type` | string | | `certificate.key_size` | integer | | `certificate.signature_algorithm` | string | | `certificate.fingerprint_sha256` | string | | `certificate.serial_number` | string | | `chain` | object | | `chain.length` | integer | | `chain.valid` | boolean | | `chain.certificates[]` | object[] | | `chain.certificates[]` | object | | `chain.certificates[].subject` | string | | `chain.certificates[].issuer` | string | | `chain.certificates[].type` | string | | `chain.certificates[].valid_from` | string | | `chain.certificates[].valid_until` | string | | `chain.issues[]` | string[] | | `security` | object | | `security.forward_secrecy` | boolean | | `security.forward_secrecy_cipher` | string | | `security.hsts_enabled` | boolean | | `security.hsts_max_age` | integer | | `security.hsts_include_subdomains` | boolean | | `security.hsts_preload` | boolean | | `security.hsts_header` | string | | `security.hsts_preload_status` | string | | `security.hsts_preloaded_domain` | string | | `security.hsts_preload_eligible` | boolean | | `security.hsts_final_url` | string | | `security.hsts_errors[]` | string[] | | `security.alpn_negotiated` | string | | `security.ocsp_stapling` | boolean | | `security.ocsp_stapling_fresh` | boolean | | `security.ocsp_stapling_status` | string \| null | | `security.ocsp_stapling_this_update` | string \| null | | `security.ocsp_stapling_next_update` | string \| null | | `security.sct_embedded` | boolean | | `security.sct_count` | integer | | `security.ct_compliance` | boolean | | `security.must_staple` | boolean | | `security.secure_renegotiation` | boolean | | `revocation` | object | | `revocation.ocsp` | object | | `revocation.ocsp.present` | boolean | | `revocation.ocsp.uris[]` | string[] | | `revocation.ocsp.checked_uri` | string \| null | | `revocation.ocsp.status` | string \| null | | `revocation.ocsp.verify_ok` | boolean | | `revocation.ocsp.this_update` | string \| null | | `revocation.ocsp.next_update` | string \| null | | `revocation.ocsp.error` | string \| null | | `revocation.crl` | object | | `revocation.crl.present` | boolean | | `revocation.crl.uris[]` | string[] | | `revocation.crl.checked_uri` | string \| null | | `revocation.crl.fetched` | boolean | | `revocation.crl.http_status` | integer \| null | | `revocation.crl.revoked` | boolean \| null | | `revocation.crl.last_update` | string \| null | | `revocation.crl.next_update` | string \| null | | `revocation.crl.revoked_serial_count` | integer \| null | | `revocation.crl.error` | string \| null | | `grade_delta` | object | | `grade_delta.current_grade` | string \| null | | `grade_delta.score` | integer \| null | | `grade_delta.next_grade` | string \| null | | `grade_delta.points_to_next_grade` | integer \| null | | `grade_delta.top_blockers[]` | string[] | | `issues[]` | string[] | | `recommendations[]` | string[] | | `checked_at` | string | | `check_duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ssl/grade?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/ssl/grade?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ssl/grade?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ssl/grade?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ssl/grade?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "cloudflare.com", "grade": "A+", "score": 98, "protocol_support": { "tls_1_3": true, "tls_1_2": true, "tls_1_1": false, "tls_1_0": false, "ssl_3": false, "preferred_protocol": "TLSv1.3", "detection_method": "active" }, "certificate": { "subject": "cloudflare.com", "issuer": "Google Trust Services", "valid_from": "2026-03-01T00:00:00Z", "valid_until": "2026-05-30T23:59:59Z", "days_remaining": 42, "expired": false, "san": [ "cloudflare.com", "*.cloudflare.com" ], "key_type": "ECDSA", "key_size": 256, "signature_algorithm": "ecdsaWithSHA256", "fingerprint_sha256": "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99" }, "chain": { "length": 3, "valid": true, "certificates": [ { "subject": "cloudflare.com", "issuer": "Google Trust Services", "type": "leaf" }, { "subject": "Google Trust Services", "issuer": "GlobalSign", "type": "intermediate" }, { "subject": "GlobalSign", "issuer": "GlobalSign", "type": "root" } ], "issues": [] }, "security": { "forward_secrecy": true, "forward_secrecy_cipher": "TLS_AES_256_GCM_SHA384", "hsts_enabled": true, "hsts_max_age": 31536000, "hsts_include_subdomains": true, "hsts_preload": true, "hsts_header": "max-age=31536000; includeSubDomains; preload", "hsts_preload_status": "preloaded", "hsts_preloaded_domain": "cloudflare.com", "hsts_preload_eligible": true, "hsts_final_url": "https://cloudflare.com/", "hsts_errors": [], "alpn_negotiated": "h2", "ocsp_stapling": true, "ocsp_stapling_fresh": true, "ocsp_stapling_status": "successful (0x0)", "ocsp_stapling_this_update": "2026-04-15T02:35:16Z", "ocsp_stapling_next_update": "2026-04-22T01:35:15Z", "ct_compliance": true, "must_staple": false, "sct_embedded": true, "sct_count": 2 }, "revocation": { "ocsp": { "present": true, "uris": [ "http://o.pki.goog/wr2" ], "checked_uri": "http://o.pki.goog/wr2", "status": "good", "verify_ok": true, "this_update": "2026-04-18T20:30:00Z", "next_update": "2026-04-19T20:30:00Z", "error": null }, "crl": { "present": true, "uris": [ "http://c.pki.goog/wr2.crl" ], "checked_uri": "http://c.pki.goog/wr2.crl", "fetched": true, "http_status": 200, "revoked": false, "last_update": "2026-04-17T00:00:00Z", "next_update": "2026-04-24T00:00:00Z", "revoked_serial_count": 0, "error": null } }, "grade_delta": { "current_grade": "A+", "score": 98, "next_grade": null, "points_to_next_grade": null, "top_blockers": [] }, "issues": [], "recommendations": [], "checked_at": "2026-04-18T21:00:00Z", "check_duration_ms": 142 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/ssl/chain` Operation: `getSslChain` Credits and authentication: 3 Authentication required GET /v1/ssl/chain Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `chain[]` | object[] | | `chain[]` | object | | `chain[].subject` | string | | `chain[].issuer` | string | | `chain[].type` | string | | `chain[].valid_from` | string \| null | | `chain[].valid_until` | string \| null | | `chain_length` | integer | | `root_trusted` | boolean | | `chain_valid` | boolean | | `certificate` | object | | `certificate.subject` | string | | `certificate.issuer` | string | | `certificate.issuer_org` | string | | `certificate.valid_from` | string | | `certificate.valid_until` | string | | `certificate.days_remaining` | integer | | `certificate.expired` | boolean | | `certificate.san[]` | string[] | | `certificate.key_type` | string | | `certificate.key_size` | integer | | `certificate.signature_algorithm` | string | | `certificate.fingerprint_sha256` | string | | `certificate.serial_number` | string | | `protocol_support` | object | | `protocol_support.tls_1_3` | boolean | | `protocol_support.tls_1_2` | boolean | | `protocol_support.tls_1_1` | boolean | | `protocol_support.tls_1_0` | boolean | | `protocol_support.ssl_3` | boolean | | `protocol_support.preferred_protocol` | string | | `protocol_support.detection_method` | string | | `security` | object | | `security.alpn_negotiated` | string | | `security.forward_secrecy` | boolean | | `security.forward_secrecy_cipher` | string | | `security.must_staple` | boolean | | `security.sct_embedded` | boolean | | `security.sct_count` | integer | | `security.ocsp_stapling` | boolean | | `security.ocsp_stapling_fresh` | boolean | | `security.ocsp_stapling_status` | string \| null | | `security.ocsp_stapling_this_update` | string \| null | | `security.ocsp_stapling_next_update` | string \| null | | `issues[]` | string[] | | `remediation_hints[]` | string[] | | `revocation` | object | | `revocation.ocsp` | object | | `revocation.ocsp.present` | boolean | | `revocation.ocsp.uris[]` | string[] | | `revocation.ocsp.checked_uri` | string \| null | | `revocation.ocsp.status` | string \| null | | `revocation.ocsp.verify_ok` | boolean | | `revocation.ocsp.this_update` | string \| null | | `revocation.ocsp.next_update` | string \| null | | `revocation.ocsp.error` | string \| null | | `revocation.crl` | object | | `revocation.crl.present` | boolean | | `revocation.crl.uris[]` | string[] | | `revocation.crl.checked_uri` | string \| null | | `revocation.crl.fetched` | boolean | | `revocation.crl.http_status` | integer \| null | | `revocation.crl.revoked` | boolean \| null | | `revocation.crl.last_update` | string \| null | | `revocation.crl.next_update` | string \| null | | `revocation.crl.revoked_serial_count` | integer \| null | | `revocation.crl.error` | string \| null | | `checked_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ssl/chain?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/ssl/chain?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ssl/chain?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ssl/chain?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ssl/chain?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "cloudflare.com", "chain": [ { "subject": "cloudflare.com", "issuer": "Google Trust Services", "type": "leaf", "valid_from": "2026-03-01T00:00:00Z", "valid_until": "2026-05-30T23:59:59Z" }, { "subject": "Google Trust Services", "issuer": "GlobalSign", "type": "intermediate", "valid_from": "2024-01-01T00:00:00Z", "valid_until": "2029-01-01T00:00:00Z" } ], "chain_valid": true, "chain_length": 2, "root_trusted": true, "certificate": { "subject": "cloudflare.com", "issuer": "Google Trust Services", "valid_from": "2026-03-01T00:00:00Z", "valid_until": "2026-05-30T23:59:59Z", "days_remaining": 42, "expired": false, "san": [ "cloudflare.com", "*.cloudflare.com" ], "key_type": "ECDSA", "key_size": 256, "signature_algorithm": "ecdsaWithSHA256", "fingerprint_sha256": "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99" }, "protocol_support": { "tls_1_3": true, "tls_1_2": true, "tls_1_1": false, "tls_1_0": false, "ssl_3": false, "preferred_protocol": "TLSv1.3", "detection_method": "active" }, "security": { "alpn_negotiated": "h2", "forward_secrecy": true, "forward_secrecy_cipher": "TLS_AES_256_GCM_SHA384", "must_staple": false, "sct_embedded": true, "sct_count": 2, "ocsp_stapling": true, "ocsp_stapling_fresh": true, "ocsp_stapling_status": "successful (0x0)", "ocsp_stapling_this_update": "2026-04-15T02:35:16Z", "ocsp_stapling_next_update": "2026-04-22T01:35:15Z" }, "issues": [], "remediation_hints": [], "revocation": { "ocsp": { "present": true, "uris": [ "http://o.pki.goog/wr2" ], "checked_uri": "http://o.pki.goog/wr2", "status": "good", "verify_ok": true, "this_update": "2026-04-18T20:30:00Z", "next_update": "2026-04-19T20:30:00Z", "error": null }, "crl": { "present": true, "uris": [ "http://c.pki.goog/wr2.crl" ], "checked_uri": "http://c.pki.goog/wr2.crl", "fetched": true, "http_status": 200, "revoked": false, "last_update": "2026-04-17T00:00:00Z", "next_update": "2026-04-24T00:00:00Z", "revoked_serial_count": 0, "error": null } }, "checked_at": "2026-04-18T21:00:00Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/ssl/expiring` Operation: `getSslExpiring` Credits and authentication: 1 Authentication required GET /v1/ssl/expiring Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | days | integer Default `30` | optional | | threshold_days | integer | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `certificate_status` | string | | `expiring_soon` | boolean | | `expired` | boolean | | `days_remaining` | integer | | `valid_from` | string | | `valid_until` | string | | `subject` | string | | `issuer` | string | | `urgency` | string | | `recommendation` | string | | `checked_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/ssl/expiring?domain=example.com&days=30&threshold_days=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/ssl/expiring?domain=example.com&days=30&threshold_days=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/ssl/expiring?domain=example.com&days=30&threshold_days=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/ssl/expiring?domain=example.com&days=30&threshold_days=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/ssl/expiring?domain=example.com&days=30&threshold_days=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "certificate_status": "found", "expiring_soon": true, "expired": false, "days_remaining": 25, "valid_from": "2026-08-05T08:12:44Z", "valid_until": "2026-11-03T08:12:43Z", "subject": "/CN=www.example.com", "issuer": "/C=US/O=Let's Encrypt/CN=R11", "urgency": "notice", "recommendation": "Certificate expires in 25 days - plan renewal", "checked_at": "2026-10-09T10:15:30.000Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/vulnerability-intelligence # Website Vulnerability Scanner API Find exposed software, risky configurations, and known affected versions across a public website. Every result explains what was checked, why it matched, and how strong the evidence is. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/website-vulnerability-scanner-api) ## Operations GET `/v1/vulnerabilities` [View API reference](https://domscan.net/docs/products/vulnerability-intelligence#getVulnerabilities) ## GET `/v1/vulnerabilities` Operation: `getVulnerabilities` Credits and authentication: 8-12 Authentication required GET /v1/vulnerabilities Credits: 8-12 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | | mode | string Allowed values `standard`, `deep` Default `standard` | optional | #### Response fields | Field | Type | | --- | --- | | `target` | object | | `target.requested_url` | string | | `target.final_url` | string | | `target.hostname` | string | | `scan` | object | | `scan.mode` | string | | `scan.status` | string | | `scan.checked_at` | string | | `scan.duration_ms` | integer | | `scan.disclaimer` | string | | `summary` | object | | `summary.posture` | string | | `summary.risk_level` | string | | `summary.finding_count` | integer | | `summary.version_affected_count` | integer | | `summary.misconfiguration_count` | integer | | `summary.urgent_count` | integer | | `summary.severity_counts` | object | | `findings[]` | object[] | | `findings[]` | object | | `findings[].fingerprint` | string | | `findings[].classification` | string | | `findings[].severity` | string | | `findings[].priority` | string | | `findings[].title` | string | | `findings[].summary` | string | | `findings[].component` | object | | `findings[].component.technology_id` | string | | `findings[].component.name` | string | | `findings[].component.detected_version` | string | | `findings[].component.version_kind` | string | | `findings[].component.confidence` | string | | `findings[].component.confidence_score` | integer | | `findings[].component.ecosystem` | string | | `findings[].component.package` | string | | `findings[].component.purl` | string | | `findings[].advisory` | object | | `findings[].advisory.id` | string | | `findings[].advisory.aliases[]` | string[] | | `findings[].advisory.cves[]` | string[] | | `findings[].advisory.published_at` | string \| null | | `findings[].advisory.modified_at` | string \| null | | `findings[].advisory.cvss[]` | object[] | | `findings[].advisory.cvss[]` | object | | `findings[].advisory.cvss[].type` | string | | `findings[].advisory.cvss[].vector` | string | | `findings[].advisory.fixed_versions[]` | string[] | | `findings[].advisory.affected_ranges[]` | object[] | | `findings[].advisory.affected_ranges[]` | object | | `findings[].advisory.references[]` | string[] | | `findings[].exploitation` | object | | `findings[].exploitation.cisa_kev` | boolean \| null | | `findings[].exploitation.kev_added_at` | string \| null | | `findings[].exploitation.kev_required_action` | string \| null | | `findings[].exploitation.known_ransomware_use` | string \| null | | `findings[].exploitation.epss_probability` | number \| null | | `findings[].exploitation.epss_percentile` | number \| null | | `findings[].exploitation.epss_date` | string \| null | | `findings[].evidence` | object | | `findings[].evidence.confidence` | string | | `findings[].evidence.observed[]` | string[] | | `findings[].evidence.limitations[]` | string[] | | `findings[].remediation` | object | | `findings[].remediation.summary` | string | | `findings[].remediation.fixed_versions[]` | string[] | | `findings[].sources[]` | string[] | | `components[]` | object[] | | `components[]` | object | | `components[].technology_id` | string | | `components[].name` | string | | `components[].detected_version` | string \| null | | `components[].version_kind` | string \| null | | `components[].confidence` | string | | `components[].advisory_status` | string | | `components[].matched_advisories` | integer | | `coverage` | object | | `coverage.target_response` | string | | `coverage.technology_detection` | string | | `coverage.package_advisories` | string | | `coverage.known_exploitation` | string | | `coverage.exploitation_probability` | string | | `coverage.detected_components` | integer | | `coverage.versioned_components` | integer | | `coverage.advisory_eligible_components` | integer | | `coverage.advisory_checked_components` | integer | | `coverage.advisory_deferred_components` | integer | | `coverage.advisory_query_limit` | integer | | `coverage.relay_used` | boolean | | `coverage.limitations[]` | string[] | | `sources[]` | object[] | | `sources[]` | object | | `sources[].id` | string | | `sources[].name` | string | | `sources[].owner` | string | | `sources[].url` | string | | `sources[].status` | string | | `sources[].retrieved_at` | string \| null | | `sources[].cache_hit` | boolean | | `sources[].expected_freshness` | string | | `sources[].fallback_behavior` | string | | `sources[].cost` | string | | `_meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/vulnerabilities?url=https%3A%2F%2Fexample.com&domain=example.com&mode=standard" ``` ```javascript const response = await fetch("https://domscan.net/v1/vulnerabilities?url=https%3A%2F%2Fexample.com&domain=example.com&mode=standard", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/vulnerabilities?url=https%3A%2F%2Fexample.com&domain=example.com&mode=standard", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/vulnerabilities?url=https%3A%2F%2Fexample.com&domain=example.com&mode=standard", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/vulnerabilities?url=https%3A%2F%2Fexample.com&domain=example.com&mode=standard") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "target": { "requested_url": "https://www.example.com/", "final_url": "https://www.example.com/", "hostname": "www.example.com" }, "scan": { "mode": "standard", "status": "complete", "checked_at": "2026-10-09T10:15:30.000Z", "duration_ms": 3120, "disclaimer": "A clean result means DomScan did not detect an issue within the documented scan coverage. Automated scanning cannot prove that an application is vulnerability-free or replace an authorized penetration test." }, "summary": { "posture": "review", "risk_level": "medium", "finding_count": 2, "version_affected_count": 0, "misconfiguration_count": 2, "urgent_count": 0, "severity_counts": { "critical": 0, "high": 0, "medium": 1, "low": 1, "info": 0, "unknown": 0 } }, "findings": [ { "fingerprint": "configuration:content-security-policy:www.example.com", "classification": "security_misconfiguration", "severity": "medium", "priority": "elevated", "title": "Content Security Policy is not advertised", "summary": "The observed response did not include a Content-Security-Policy header.", "evidence": { "confidence": "high", "observed": [ "Public response did not include the expected content-security-policy protection." ], "limitations": [ "header_policy_can_vary_by_path_or_response_status" ] }, "remediation": { "summary": "Deploy a restrictive Content Security Policy in report-only mode first, then enforce it.", "fixed_versions": [] }, "sources": [ "target_response" ] }, { "fingerprint": "configuration:referrer-policy:www.example.com", "classification": "security_misconfiguration", "severity": "low", "priority": "normal", "title": "Referrer Policy is not advertised", "summary": "The response did not include an explicit Referrer-Policy header.", "evidence": { "confidence": "high", "observed": [ "Public response did not include the expected referrer-policy protection." ], "limitations": [ "header_policy_can_vary_by_path_or_response_status" ] }, "remediation": { "summary": "Choose and deploy a Referrer-Policy that matches the application privacy and analytics requirements.", "fixed_versions": [] }, "sources": [ "target_response" ] } ], "components": [ { "technology_id": "jquery", "name": "jQuery", "detected_version": "3.7.1", "version_kind": "asset", "confidence": "high", "advisory_status": "checked", "matched_advisories": 0 }, { "technology_id": "cloudflare", "name": "Cloudflare", "detected_version": null, "version_kind": null, "confidence": "high", "advisory_status": "mapping_unavailable", "matched_advisories": 0 } ], "coverage": { "target_response": "checked", "technology_detection": "checked", "package_advisories": "checked", "known_exploitation": "not_requested", "exploitation_probability": "not_requested", "detected_components": 2, "versioned_components": 1, "advisory_eligible_components": 1, "advisory_checked_components": 1, "advisory_deferred_components": 0, "advisory_query_limit": 20, "relay_used": true, "limitations": [ "Only exact reviewed technology-to-package mappings are checked against OSV.", "Versionless or semantically incompatible detections are not reported as vulnerable.", "This passive scan does not send exploit payloads or prove exploitability.", "Response headers and exposed versions can vary by path, edge location, or authentication state." ] }, "sources": [ { "id": "target_response", "name": "Observed public response", "owner": "Target website", "url": "https://domscan.net/tech-stack-api", "status": "checked", "retrieved_at": "2026-10-09T10:15:30.000Z", "cache_hit": false, "expected_freshness": "Live at scan time", "fallback_behavior": "Unavailable signals remain unknown and never imply that the target is unaffected", "cost": "none" }, { "id": "osv", "name": "OSV", "owner": "Google Open Source Security Team", "url": "https://google.github.io/osv.dev/", "status": "checked", "retrieved_at": "2026-10-09T10:15:29.000Z", "cache_hit": false, "expected_freshness": "OSV targets advisory freshness within 15 minutes", "fallback_behavior": "Use a fresh cached result when available; otherwise mark the component advisory check unknown", "cost": "none" }, { "id": "cisa_kev", "name": "CISA Known Exploited Vulnerabilities Catalog", "owner": "Cybersecurity and Infrastructure Security Agency", "url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", "status": "not_requested", "retrieved_at": null, "cache_hit": false, "expected_freshness": "Catalog changes are checked hourly", "fallback_behavior": "Use a fresh cached catalog when available; otherwise leave exploitation status unknown", "cost": "none" }, { "id": "first_epss", "name": "Exploit Prediction Scoring System", "owner": "FIRST", "url": "https://www.first.org/epss/", "status": "not_requested", "retrieved_at": null, "cache_hit": false, "expected_freshness": "Scores are generated daily", "fallback_behavior": "Return the advisory without an EPSS value and mark exploitation probability unknown", "cost": "none" } ], "_meta": { "served_by": "pop=MAD country=ES", "analysis_status": "complete" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `503` Service Unavailable ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/security-headers # Security headers API API Grade HSTS, CSP, frame protection and other HTTP security headers. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/security-headers-api) ## Operations GET `/v1/headers` [View API reference](https://domscan.net/docs/products/security-headers#getSecurityHeadersAudit) ## GET `/v1/headers` Operation: `getSecurityHeadersAudit` Credits and authentication: 1 Authentication required GET /v1/headers Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | url | string | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `url` | string | | `domain` | string | | `status` | string | | `checked_at` | string | | `final_url` | string \| null | | `http_status` | integer \| null | | `redirect_count` | integer \| null | | `https` | boolean \| null | | `score` | integer \| null | | `grade` | string \| null | | `summary` | object | | `summary.passed` | integer | | `summary.warned` | integer | | `summary.failed` | integer | | `summary.missing` | integer | | `summary.not_applicable` | integer | | `summary.hsts_preload_ready` | boolean | | `summary.csp_strict` | boolean | | `checks[]` | object[] | | `checks[]` | object | | `checks[].id` | string | | `checks[].status` | string | | `checks[].value` | string \| null | | `checks[].detail_code` | string | | `checks[].issues[]` | string[] | | `checks[].weight` | integer | | `checks[].classification` | object | | `checks[].classification.status` | string | | `checks[].classification.reason` | string | | `checks[].classification.evidence` | object | | `checks[].classification.evidence.source` | string | | `checks[].classification.evidence.method` | string | | `checks[].classification.evidence.observed_at` | string | | `checks[].classification.evidence.detail` | string | | `checks[].classification.checked_at` | string | | `cookies[]` | object[] | | `cookies[]` | object | | `cookies[].name` | string | | `cookies[].secure` | boolean | | `cookies[].http_only` | boolean | | `cookies[].same_site` | string \| null | | `cookies[].issues[]` | string[] | | `headers_raw` | object | | `recommendations[]` | string[] | | `fetch` | object | | `fetch.checked_url` | string | | `fetch.http_status` | integer \| null | | `fetch.final_url` | string \| null | | `fetch.via_proxy` | boolean \| null | | `fetch.redirect_count` | integer \| null | | `fetch.unknown_reason` | string \| null | | `caveats[]` | string[] | | `rubric_version` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/headers?url=https%3A%2F%2Fexample.com&domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/headers?url=https%3A%2F%2Fexample.com&domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/headers?url=https%3A%2F%2Fexample.com&domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/headers?url=https%3A%2F%2Fexample.com&domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/headers?url=https%3A%2F%2Fexample.com&domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "url": "https://example.com/", "domain": "example.com", "status": "ok", "checked_at": "2026-10-09T10:15:30.000Z", "final_url": "https://www.example.com/", "http_status": 200, "redirect_count": 1, "https": true, "score": 75, "grade": "C", "summary": { "passed": 6, "warned": 2, "failed": 0, "missing": 2, "not_applicable": 1, "hsts_preload_ready": false, "csp_strict": false }, "checks": [ { "id": "strict_transport_security", "status": "pass", "value": "max-age=31536000", "detail_code": "enabled", "issues": [ "include_subdomains_missing", "preload_missing" ], "weight": 20 }, { "id": "content_security_policy", "status": "warn", "value": "default-src 'self'; script-src 'self' 'unsafe-inline'", "detail_code": "unsafe_inline", "issues": [ "missing_object_src", "missing_base_uri", "unsafe_inline" ], "weight": 25 }, { "id": "clickjacking", "status": "pass", "value": "SAMEORIGIN", "detail_code": "x_frame_options_sameorigin", "issues": [], "weight": 10 }, { "id": "x_content_type_options", "status": "pass", "value": "nosniff", "detail_code": "nosniff", "issues": [], "weight": 10 }, { "id": "referrer_policy", "status": "pass", "value": "strict-origin-when-cross-origin", "detail_code": "strict_origin_when_cross_origin", "issues": [], "weight": 10 }, { "id": "permissions_policy", "status": "missing", "value": null, "detail_code": "header_missing", "issues": [], "weight": 5 }, { "id": "cross_origin_opener_policy", "status": "pass", "value": "same-origin", "detail_code": "same_origin", "issues": [], "weight": 5 }, { "id": "cross_origin_embedder_policy", "status": "not_applicable", "value": null, "detail_code": "not_set_informational", "issues": [], "weight": 0 }, { "id": "cross_origin_resource_policy", "status": "missing", "value": null, "detail_code": "header_missing", "issues": [], "weight": 5 }, { "id": "information_disclosure", "status": "warn", "value": "server: nginx/1.25.3", "detail_code": "version_disclosed", "issues": [ "server_version_disclosed" ], "weight": 5 }, { "id": "cookies", "status": "pass", "value": "session", "detail_code": "all_flags_set", "issues": [], "weight": 5 } ], "cookies": [ { "name": "session", "secure": true, "http_only": true, "same_site": "lax", "issues": [] } ], "headers_raw": { "strict-transport-security": "max-age=31536000", "content-security-policy": "default-src 'self'; script-src 'self' 'unsafe-inline'", "x-frame-options": "SAMEORIGIN", "x-content-type-options": "nosniff", "referrer-policy": "strict-origin-when-cross-origin", "cross-origin-opener-policy": "same-origin", "server": "nginx/1.25.3" }, "recommendations": [ "remove_csp_unsafe_inline", "add_csp_object_src_none", "add_csp_base_uri", "add_hsts_include_subdomains", "add_hsts_preload", "add_permissions_policy", "add_cross_origin_resource_policy", "hide_server_version" ], "fetch": { "checked_url": "https://example.com/", "http_status": 200, "final_url": "https://www.example.com/", "via_proxy": true, "redirect_count": 1, "unknown_reason": null }, "caveats": [ "set_cookie_visibility_limited", "meta_csp_not_evaluated" ], "rubric_version": "2026-10-09.1" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/security-txt # security.txt API API Validate security.txt contacts, expiry and RFC 9116 fields. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/security-txt-api) ## Operations GET `/v1/security-txt` [View API reference](https://domscan.net/docs/products/security-txt#getSecurityTxt) ## GET `/v1/security-txt` Operation: `getSecurityTxt` Credits and authentication: 1 Authentication required GET /v1/security-txt Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | optional | | url | string | optional | #### Response fields | Field | Type | | --- | --- | | `classification` | object | | `classification.status` | string | | `classification.reason` | string | | `classification.evidence` | object | | `classification.evidence.source` | string | | `classification.evidence.method` | string | | `classification.evidence.observed_at` | string | | `classification.evidence.detail` | string | | `classification.checked_at` | string | | `domain` | string | | `status` | string | | `location` | string \| null | | `checked_at` | string | | `fetch[]` | object[] | | `fetch[]` | object | | `fetch[].location` | string | | `fetch[].checked_url` | string | | `fetch[].http_status` | integer \| null | | `fetch[].final_url` | string \| null | | `fetch[].via_proxy` | boolean \| null | | `fetch[].content_type` | string \| null | | `fetch[].bytes` | integer \| null | | `fetch[].truncated` | boolean | | `fetch[].outcome` | string | | `fetch[].error` | string \| null | | `fields` | object | | `fields.contact[]` | string[] | | `fields.expires` | string \| null | | `fields.expires_in_days` | integer \| null | | `fields.encryption[]` | string[] | | `fields.acknowledgments[]` | string[] | | `fields.preferred_languages[]` | string[] | | `fields.canonical[]` | string[] | | `fields.policy[]` | string[] | | `fields.hiring[]` | string[] | | `fields.csaf[]` | string[] | | `fields.other_fields[]` | object[] | | `fields.other_fields[]` | object | | `fields.other_fields[].name` | string | | `fields.other_fields[].value` | string | | `signed` | boolean | | `issues[]` | object[] | | `issues[]` | object | | `issues[].code` | string | | `issues[].severity` | string | | `issues[].field` | string \| null | | `caveats[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/security-txt?domain=example.com&url=https%3A%2F%2Fexample.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/security-txt?domain=example.com&url=https%3A%2F%2Fexample.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/security-txt?domain=example.com&url=https%3A%2F%2Fexample.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/security-txt?domain=example.com&url=https%3A%2F%2Fexample.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/security-txt?domain=example.com&url=https%3A%2F%2Fexample.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "status": "valid", "location": "well_known", "checked_at": "2026-10-09T10:00:00.000Z", "fetch": [ { "location": "well_known", "checked_url": "https://example.com/.well-known/security.txt", "http_status": 200, "final_url": "https://example.com/.well-known/security.txt", "via_proxy": true, "content_type": "text/plain; charset=utf-8", "bytes": 279, "truncated": false, "outcome": "found", "error": null } ], "fields": { "contact": [ "mailto:security@example.com", "https://example.com/report" ], "expires": "2027-01-01T00:00:00.000Z", "expires_in_days": 83, "encryption": [ "https://example.com/pgp-key.txt" ], "acknowledgments": [], "preferred_languages": [ "en", "es" ], "canonical": [ "https://example.com/.well-known/security.txt" ], "policy": [ "https://example.com/security-policy" ], "hiring": [], "csaf": [], "other_fields": [] }, "signed": false, "issues": [], "caveats": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/domain-reputation # Domain Reputation API Check domain reputation across multiple threat intelligence sources. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-reputation-api) ## Operations GET `/v1/reputation` [View API reference](https://domscan.net/docs/products/domain-reputation#getDomainReputation) ## GET `/v1/reputation` Operation: `getDomainReputation` Credits and authentication: 3 Authentication required GET /v1/reputation Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `reputation_score` | integer | | `grade` | string | | `risk_level` | string | | `reputation_score_confidence` | string | | `grade_capped_by_parking` | boolean | | `factors` | object | | `factors.age` | object | | `factors.dns_security` | object | | `factors.ssl_certificate` | object | | `factors.hosting` | object | | `factors.web_presence` | object | | `factors.blacklists` | object | | `factors.email_config` | object | | `recommendations[]` | object[] | | `recommendations[]` | object | | `recommendations[].priority` | string | | `recommendations[].category` | string | | `recommendations[].action` | string | | `recommendations[].impact` | string | | `evidence_summary` | object | | `evidence_summary.checks_performed` | integer | | `evidence_summary.cache_status` | string | | `evidence_summary.confidence` | string | | `evidence_summary.risk_level` | string | | `evidence_summary.factor_count` | integer | | `evidence_summary.scored_factor_count` | integer | | `evidence_summary.passing_factor_count` | integer | | `evidence_summary.warning_factor_count` | integer | | `evidence_summary.failing_factor_count` | integer | | `evidence_summary.lowest_scoring_factors[]` | object[] | | `evidence_summary.lowest_scoring_factors[]` | object | | `evidence_summary.lowest_scoring_factors[].name` | string | | `evidence_summary.lowest_scoring_factors[].score` | number \| null | | `evidence_summary.lowest_scoring_factors[].weight` | number \| null | | `evidence_summary.blacklist_listed_count` | integer | | `evidence_summary.recommendation_count` | integer | | `evidence_summary.high_priority_recommendation_count` | integer | | `evidence_summary.grade_capped_by_parking` | boolean | | `meta` | object | | `meta.query_time_ms` | integer | | `meta.checks_performed` | integer | | `meta.cached` | boolean | | `meta.served_by` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/reputation?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/reputation?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/reputation?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/reputation?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/reputation?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "reputation_score": 69, "grade": "C", "risk_level": "medium", "reputation_score_confidence": "high", "grade_capped_by_parking": true, "factors": { "age": { "score": 84, "weight": 0.1, "details": { "age_days": 5840 } }, "dns_security": { "score": 80, "weight": 0.2, "details": { "dnssec": false, "spf": true, "dmarc": true, "dmarc_policy": "reject" } }, "ssl_certificate": { "score": 92, "weight": 0.2, "details": { "valid": true, "error": null, "grade": "A", "chain_valid": true, "min_tls_version": "TLSv1.3" } }, "hosting": { "score": 35, "weight": 0.1, "details": { "has_a_records": true, "a_record_count": 2, "parked": true } }, "web_presence": { "score": 20, "weight": 0.15, "details": { "has_website": true, "redirects_to_https": true, "response_time_ms": 87, "parked": true, "for_sale": false, "parking_provider": "Example Parking" } }, "blacklists": { "score": 100, "weight": 0.1, "details": { "listed": false, "threat_level": "none", "domain_sources": [], "ip_sources": [] } }, "email_config": { "score": 100, "weight": 0.15, "details": { "has_mx": true, "has_spf": true, "has_dmarc": true, "mx_count": 2 } } }, "recommendations": [ { "priority": "high", "category": "web_presence", "action": "Move the domain off parking if it is intended for customer traffic.", "impact": "+10 points" } ], "meta": { "query_time_ms": 187, "checks_performed": 7, "cached": false, "served_by": "pop=MAD country=ES" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/email-authentication # Email Authentication API Analyze email authentication records including SPF, DKIM, and DMARC. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/email-auth-api) ## Operations GET `/v1/email-auth` [View API reference](https://domscan.net/docs/products/email-authentication#getEmailAuth) POST `/v1/email-auth/bulk` [View API reference](https://domscan.net/docs/products/email-authentication#bulkGetEmailAuth) POST `/v1/tools/spf/build` [View API reference](https://domscan.net/docs/products/email-authentication#buildSpf)[Read the guide](https://domscan.net/spf-builder-api) POST `/v1/tools/spf/validate` [View API reference](https://domscan.net/docs/products/email-authentication#validateSpf)[Read the guide](https://domscan.net/spf-validator-api) POST `/v1/tools/spf/flatten` [View API reference](https://domscan.net/docs/products/email-authentication#flattenSpf)[Read the guide](https://domscan.net/spf-flattener-api) POST `/v1/tools/dmarc/build` [View API reference](https://domscan.net/docs/products/email-authentication#buildDmarc)[Read the guide](https://domscan.net/dmarc-builder-api) POST `/v1/tools/dmarc/validate` [View API reference](https://domscan.net/docs/products/email-authentication#validateDmarc)[Read the guide](https://domscan.net/dmarc-validator-api) GET `/v1/tools/dkim/check` [View API reference](https://domscan.net/docs/products/email-authentication#checkDkim)[Read the guide](https://domscan.net/dkim-check-api) GET `/v1/tools/dkim/discover` [View API reference](https://domscan.net/docs/products/email-authentication#discoverDkim)[Read the guide](https://domscan.net/dkim-discovery-api) ## GET `/v1/email-auth` Operation: `getEmailAuth` Credits and authentication: 3 Authentication required GET /v1/email-auth Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | selectors | string | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `spf` | object | | `spf.classification` | object | | `spf.classification.status` | string | | `spf.classification.reason` | string | | `spf.classification.evidence` | object | | `spf.classification.evidence.source` | string | | `spf.classification.evidence.method` | string | | `spf.classification.evidence.observed_at` | string | | `spf.classification.evidence.detail` | string | | `spf.classification.checked_at` | string | | `spf.record` | string \| null | | `spf.lookup_estimate` | integer | | `spf.includes[]` | string[] | | `spf.redirect` | string \| null | | `spf.macros_present` | boolean | | `spf.macro_references[]` | string[] | | `spf.lookup_walk_count` | integer | | `spf.lookup_limit_exceeded` | boolean | | `spf.walk[]` | object[] | | `spf.walk[]` | object | | `spf.walk[].domain` | string | | `spf.walk[].depth` | integer | | `spf.walk[].record` | string | | `spf.walk[].mechanisms[]` | string[] | | `spf.walk[].includes[]` | string[] | | `spf.walk[].redirect` | string \| null | | `spf.walk[].direct_lookup_count` | integer | | `spf.walk[].total_lookup_count` | integer | | `spf.walk[].macros_present` | boolean | | `spf.walk[].macro_references[]` | string[] | | `spf.walk[].multiple_records` | integer | | `spf.walk_errors[]` | string[] | | `spf.lookup_tree` | object | | `spf.lookup_tree.root_domain` | string | | `spf.lookup_tree.node_count` | integer | | `spf.lookup_tree.max_depth` | integer | | `spf.lookup_tree.cycles_detected[]` | string[] | | `spf.lookup_tree.nodes[]` | object[] | | `spf.lookup_tree.nodes[]` | object | | `spf.lookup_tree.nodes[].domain` | string | | `spf.lookup_tree.nodes[].depth` | integer | | `spf.lookup_tree.nodes[].status` | string | | `spf.lookup_tree.nodes[].direct_lookup_count` | integer | | `spf.lookup_tree.nodes[].total_lookup_count` | integer | | `spf.lookup_tree.nodes[].includes[]` | string[] | | `spf.lookup_tree.nodes[].redirect` | string \| null | | `spf.lookup_tree.nodes[].mechanisms[]` | string[] | | `spf.lookup_tree.nodes[].errors[]` | string[] | | `spf.lookup_tree.edges[]` | object[] | | `spf.lookup_tree.edges[]` | object | | `spf.lookup_tree.edges[].from` | string | | `spf.lookup_tree.edges[].to` | string | | `spf.lookup_tree.edges[].type` | string | | `dkim[]` | object[] | | `dkim[]` | object | | `dkim[].classification` | object | | `dkim[].classification.status` | string | | `dkim[].classification.reason` | string | | `dkim[].classification.evidence` | object | | `dkim[].classification.evidence.source` | string | | `dkim[].classification.evidence.method` | string | | `dkim[].classification.evidence.observed_at` | string | | `dkim[].classification.evidence.detail` | string | | `dkim[].classification.checked_at` | string | | `dkim[].selector` | string | | `dkim[].record` | string \| null | | `dkim[].key_type` | string \| null | | `dkim[].key_size` | integer \| null | | `dkim_audit` | object | | `dkim_audit.selectors_checked[]` | string[] | | `dkim_audit.selectors_found[]` | object[] | | `dkim_audit.selectors_found[]` | object | | `dkim_audit.selectors_found[].selector` | string | | `dkim_audit.selectors_found[].dns_name` | string | | `dkim_audit.selectors_found[].record` | string \| null | | `dkim_audit.selectors_found[].record_type` | string \| null | | `dkim_audit.selectors_found[].cname_targets[]` | string[] | | `dkim_audit.selectors_found[].provider_hint` | string \| null | | `dkim_audit.selectors_found[].key_type` | string \| null | | `dkim_audit.selectors_found[].key_size` | integer \| null | | `dkim_audit.selectors_found[].valid` | boolean | | `dkim_audit.selectors_found[].revoked` | boolean | | `dkim_audit.selectors_found[].weak` | boolean | | `dkim_audit.selectors_found[].hash_algorithms[]` | string[] | | `dkim_audit.selectors_found[].service_type` | string \| null | | `dkim_audit.selectors_found[].flags[]` | string[] | | `dkim_audit.selectors_found[].issues[]` | string[] | | `dkim_audit.total_found` | integer | | `dkim_audit.providers_detected[]` | string[] | | `dkim_audit.valid_selector_count` | integer | | `dkim_audit.weak_selector_count` | integer | | `dkim_audit.revoked_selector_count` | integer | | `bimi` | object | | `bimi.classification` | object | | `bimi.classification.status` | string | | `bimi.classification.reason` | string | | `bimi.classification.evidence` | object | | `bimi.classification.evidence.source` | string | | `bimi.classification.evidence.method` | string | | `bimi.classification.evidence.observed_at` | string | | `bimi.classification.evidence.detail` | string | | `bimi.classification.checked_at` | string | | `bimi.exists` | boolean | | `bimi.record` | string \| null | | `bimi.valid` | boolean | | `bimi.logo_url` | string \| null | | `bimi.authority_url` | string \| null | | `bimi.logo_fetch_ok` | boolean \| null | | `bimi.logo_http_status` | integer \| null | | `bimi.logo_content_type` | string \| null | | `bimi.logo_bytes` | integer \| null | | `bimi.logo_svg_detected` | boolean \| null | | `bimi.vmc_present` | boolean | | `bimi.vmc_fetched` | boolean \| null | | `bimi.vmc_http_status` | integer \| null | | `bimi.vmc_content_type` | string \| null | | `bimi.vmc_certificate_valid` | boolean \| null | | `bimi.vmc_subject` | string \| null | | `bimi.vmc_issuer` | string \| null | | `bimi.vmc_not_before` | string \| null | | `bimi.vmc_not_after` | string \| null | | `bimi.vmc_days_to_expiry` | integer \| null | | `bimi.vmc_fingerprint_sha256` | string \| null | | `bimi.vmc_san_domains[]` | string[] | | `bimi.errors[]` | string[] | | `dmarc` | object | | `dmarc.classification` | object | | `dmarc.classification.status` | string | | `dmarc.classification.reason` | string | | `dmarc.classification.evidence` | object | | `dmarc.classification.evidence.source` | string | | `dmarc.classification.evidence.method` | string | | `dmarc.classification.evidence.observed_at` | string | | `dmarc.classification.evidence.detail` | string | | `dmarc.classification.checked_at` | string | | `dmarc.record` | string \| null | | `dmarc.tags` | object | | `mta_sts` | object | | `mta_sts.classification` | object | | `mta_sts.classification.status` | string | | `mta_sts.classification.reason` | string | | `mta_sts.classification.evidence` | object | | `mta_sts.classification.evidence.source` | string | | `mta_sts.classification.evidence.method` | string | | `mta_sts.classification.evidence.observed_at` | string | | `mta_sts.classification.evidence.detail` | string | | `mta_sts.classification.checked_at` | string | | `mta_sts.exists` | boolean | | `mta_sts.record` | string \| null | | `mta_sts.valid` | boolean | | `mta_sts.policy_id` | string \| null | | `mta_sts.policy_fetch_ok` | boolean | | `mta_sts.policy_http_status` | integer \| null | | `mta_sts.mode` | string \| null | | `mta_sts.max_age` | integer \| null | | `mta_sts.mx_hosts[]` | string[] | | `mta_sts.mx_records[]` | string[] | | `mta_sts.policy_matches_mx` | boolean \| null | | `mta_sts.uncovered_mx[]` | string[] | | `mta_sts.errors[]` | string[] | | `tls_rpt` | object | | `tls_rpt.exists` | boolean | | `tls_rpt.record` | string \| null | | `tls_rpt.valid` | boolean | | `tls_rpt.rua[]` | string[] | | `tls_rpt.errors[]` | string[] | | `client_access` | object | | `client_access.provider_hint` | object | | `client_access.provider_hint.id` | string | | `client_access.provider_hint.name` | string | | `client_access.mx_records[]` | string[] | | `client_access.services[]` | object[] | | `client_access.services[]` | object | | `client_access.services[].service` | string | | `client_access.services[].host` | string | | `client_access.services[].port` | integer | | `client_access.services[].source` | string | | `client_access.services[].priority` | integer \| null | | `client_access.services[].weight` | integer \| null | | `client_access.services[].tls_mode` | string | | `client_access.services[].reachable` | boolean | | `client_access.services[].tls_negotiated` | boolean | | `client_access.services[].starttls_offered` | boolean \| null | | `client_access.services[].protocol` | string \| null | | `client_access.services[].cipher` | string \| null | | `client_access.services[].certificate` | object | | `client_access.services[].certificate.subject` | string | | `client_access.services[].certificate.issuer` | string | | `client_access.services[].certificate.not_before` | string | | `client_access.services[].certificate.not_after` | string | | `client_access.services[].certificate.days_to_expiry` | integer | | `client_access.services[].certificate.expired` | boolean | | `client_access.services[].certificate.san_domains[]` | string[] | | `client_access.services[].certificate.public_key_type` | string \| null | | `client_access.services[].certificate.public_key_bits` | integer \| null | | `client_access.services[].certificate.fingerprint_sha256` | string \| null | | `client_access.services[].certificate.hostname_match` | boolean \| null | | `client_access.services[].certificate.chain_valid` | boolean | | `client_access.services[].certificate.chain_error` | string \| null | | `client_access.services[].chain_depth` | integer | | `client_access.services[].error` | string \| null | | `client_access.reachable_service_count` | integer | | `client_access.secure_service_count` | integer | | `autodiscover` | object | | `autodiscover.provider_hint` | object | | `autodiscover.provider_hint.id` | string | | `autodiscover.provider_hint.name` | string | | `autodiscover.mx_records[]` | string[] | | `autodiscover.srv` | object | | `autodiscover.srv.autodiscover[]` | object[] | | `autodiscover.srv.autodiscover[]` | object | | `autodiscover.srv.autodiscover[].priority` | integer | | `autodiscover.srv.autodiscover[].weight` | integer | | `autodiscover.srv.autodiscover[].port` | integer | | `autodiscover.srv.autodiscover[].target` | string | | `autodiscover.srv.submission[]` | object[] | | `autodiscover.srv.submission[]` | object | | `autodiscover.srv.submission[].priority` | integer | | `autodiscover.srv.submission[].weight` | integer | | `autodiscover.srv.submission[].port` | integer | | `autodiscover.srv.submission[].target` | string | | `autodiscover.srv.submissions[]` | object[] | | `autodiscover.srv.submissions[]` | object | | `autodiscover.srv.submissions[].priority` | integer | | `autodiscover.srv.submissions[].weight` | integer | | `autodiscover.srv.submissions[].port` | integer | | `autodiscover.srv.submissions[].target` | string | | `autodiscover.srv.imap[]` | object[] | | `autodiscover.srv.imap[]` | object | | `autodiscover.srv.imap[].priority` | integer | | `autodiscover.srv.imap[].weight` | integer | | `autodiscover.srv.imap[].port` | integer | | `autodiscover.srv.imap[].target` | string | | `autodiscover.srv.imaps[]` | object[] | | `autodiscover.srv.imaps[]` | object | | `autodiscover.srv.imaps[].priority` | integer | | `autodiscover.srv.imaps[].weight` | integer | | `autodiscover.srv.imaps[].port` | integer | | `autodiscover.srv.imaps[].target` | string | | `autodiscover.srv.pop3[]` | object[] | | `autodiscover.srv.pop3[]` | object | | `autodiscover.srv.pop3[].priority` | integer | | `autodiscover.srv.pop3[].weight` | integer | | `autodiscover.srv.pop3[].port` | integer | | `autodiscover.srv.pop3[].target` | string | | `autodiscover.srv.pop3s[]` | object[] | | `autodiscover.srv.pop3s[]` | object | | `autodiscover.srv.pop3s[].priority` | integer | | `autodiscover.srv.pop3s[].weight` | integer | | `autodiscover.srv.pop3s[].port` | integer | | `autodiscover.srv.pop3s[].target` | string | | `autodiscover.thunderbird_autoconfig` | object | | `autodiscover.thunderbird_autoconfig.subdomain` | object | | `autodiscover.thunderbird_autoconfig.subdomain.url` | string | | `autodiscover.thunderbird_autoconfig.subdomain.status_code` | integer \| null | | `autodiscover.thunderbird_autoconfig.subdomain.content_type` | string \| null | | `autodiscover.thunderbird_autoconfig.subdomain.final_url` | string \| null | | `autodiscover.thunderbird_autoconfig.subdomain.redirect_count` | integer | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[]` | object[] | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[]` | object | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[].type` | string | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[].hostname` | string | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[].port` | integer | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[].socket_type` | string | | `autodiscover.thunderbird_autoconfig.subdomain.incoming[].username` | string | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[]` | object[] | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[]` | object | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[].type` | string | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[].hostname` | string | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[].port` | integer | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[].socket_type` | string | | `autodiscover.thunderbird_autoconfig.subdomain.outgoing[].username` | string | | `autodiscover.thunderbird_autoconfig.subdomain.error` | string \| null | | `autodiscover.thunderbird_autoconfig.well_known` | object | | `autodiscover.thunderbird_autoconfig.well_known.url` | string | | `autodiscover.thunderbird_autoconfig.well_known.status_code` | integer \| null | | `autodiscover.thunderbird_autoconfig.well_known.content_type` | string \| null | | `autodiscover.thunderbird_autoconfig.well_known.final_url` | string \| null | | `autodiscover.thunderbird_autoconfig.well_known.redirect_count` | integer | | `autodiscover.thunderbird_autoconfig.well_known.incoming[]` | object[] | | `autodiscover.thunderbird_autoconfig.well_known.incoming[]` | object | | `autodiscover.thunderbird_autoconfig.well_known.incoming[].type` | string | | `autodiscover.thunderbird_autoconfig.well_known.incoming[].hostname` | string | | `autodiscover.thunderbird_autoconfig.well_known.incoming[].port` | integer | | `autodiscover.thunderbird_autoconfig.well_known.incoming[].socket_type` | string | | `autodiscover.thunderbird_autoconfig.well_known.incoming[].username` | string | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[]` | object[] | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[]` | object | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[].type` | string | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[].hostname` | string | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[].port` | integer | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[].socket_type` | string | | `autodiscover.thunderbird_autoconfig.well_known.outgoing[].username` | string | | `autodiscover.thunderbird_autoconfig.well_known.error` | string \| null | | `autodiscover.outlook_autodiscover` | object | | `autodiscover.outlook_autodiscover.url` | string | | `autodiscover.outlook_autodiscover.status_code` | integer \| null | | `autodiscover.outlook_autodiscover.content_type` | string \| null | | `autodiscover.outlook_autodiscover.final_url` | string \| null | | `autodiscover.outlook_autodiscover.redirect_count` | integer | | `autodiscover.outlook_autodiscover.auth_required` | boolean \| null | | `autodiscover.outlook_autodiscover.error` | string \| null | | `autodiscover.recommended[]` | object[] | | `autodiscover.recommended[]` | object | | `autodiscover.recommended[].service` | string | | `autodiscover.recommended[].host` | string | | `autodiscover.recommended[].port` | integer | | `autodiscover.recommended[].tls_mode` | string | | `autodiscover.recommended[].source` | string | | `edge_summary` | object | | `edge_summary.relay_configured` | boolean | | `edge_summary.evidence_sources[]` | string[] | | `edge_summary.spf_lookup_count` | integer \| null | | `edge_summary.spf_lookup_limit_exceeded` | boolean | | `edge_summary.dkim_valid_selector_count` | integer | | `edge_summary.dkim_weak_selector_count` | integer | | `edge_summary.dkim_revoked_selector_count` | integer | | `edge_summary.providers_detected[]` | string[] | | `edge_summary.mta_sts_enforced` | boolean | | `edge_summary.tls_rpt_configured` | boolean | | `edge_summary.bimi_logo_verified` | boolean \| null | | `edge_summary.vmc_certificate_valid` | boolean \| null | | `edge_summary.client_access_reachable_services` | integer \| null | | `edge_summary.client_access_secure_services` | integer \| null | | `edge_summary.autodiscover_recommendation_count` | integer \| null | | `provider_selector_recommendations[]` | object[] | | `provider_selector_recommendations[]` | object | | `provider_selector_recommendations[].provider` | string | | `provider_selector_recommendations[].selectors[]` | string[] | | `provider_selector_recommendations[].source` | string | | `provider_selector_recommendations[].checked_selectors[]` | string[] | | `provider_selector_recommendations[].found_selectors[]` | string[] | | `provider_selector_recommendations[].missing_selectors[]` | string[] | | `grade` | string \| null | | `checks_unknown` | integer | | `score_confidence` | string | | `notes[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/email-auth?domain=example.com&selectors=google%2Cselector1%2Csendgrid" ``` ```javascript const response = await fetch("https://domscan.net/v1/email-auth?domain=example.com&selectors=google%2Cselector1%2Csendgrid", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/email-auth?domain=example.com&selectors=google%2Cselector1%2Csendgrid", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/email-auth?domain=example.com&selectors=google%2Cselector1%2Csendgrid", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email-auth?domain=example.com&selectors=google%2Cselector1%2Csendgrid") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "google.com", "spf": { "record": "v=spf1 include:_spf.google.com ~all", "lookup_estimate": 1, "includes": [ "_spf.google.com" ], "redirect": null, "macros_present": false, "macro_references": [], "lookup_walk_count": 1, "lookup_limit_exceeded": false, "walk": [ { "domain": "google.com", "depth": 0, "record": "v=spf1 include:_spf.google.com ~all", "mechanisms": [ "include:_spf.google.com", "~all" ], "includes": [ "_spf.google.com" ], "redirect": null, "direct_lookup_count": 1, "total_lookup_count": 1, "macros_present": false, "macro_references": [], "multiple_records": 1 } ], "walk_errors": [], "lookup_tree": { "root_domain": "google.com", "node_count": 1, "max_depth": 0, "cycles_detected": [], "nodes": [ { "domain": "google.com", "depth": 0, "status": "present", "direct_lookup_count": 1, "total_lookup_count": 1, "includes": [ "_spf.google.com" ], "redirect": null, "mechanisms": [ "include:_spf.google.com", "~all" ], "errors": [] } ], "edges": [ { "from": "google.com", "to": "_spf.google.com", "type": "include" } ] } }, "dkim": [ { "selector": "google", "record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A", "key_type": "rsa", "key_size": 2048 } ], "dkim_audit": { "selectors_checked": [ "google", "default", "selector1", "selector2" ], "selectors_found": [ { "selector": "google", "dns_name": "google._domainkey.google.com", "record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A", "record_type": "TXT", "cname_targets": [], "provider_hint": "Google Workspace", "key_type": "rsa", "key_size": 2048, "valid": true, "revoked": false, "weak": false, "hash_algorithms": [ "sha256" ], "service_type": "email", "flags": [ "s" ], "issues": [] } ], "total_found": 1, "providers_detected": [ "Google Workspace" ], "valid_selector_count": 1, "weak_selector_count": 0, "revoked_selector_count": 0 }, "bimi": { "exists": true, "record": "v=BIMI1; l=https://example.com/logo.svg; a=https://example.com/vmc.pem", "valid": true, "logo_url": "https://example.com/logo.svg", "authority_url": "https://example.com/vmc.pem", "logo_fetch_ok": true, "logo_http_status": 200, "logo_content_type": "image/svg+xml", "logo_bytes": 2048, "logo_svg_detected": true, "vmc_present": true, "vmc_fetched": true, "vmc_http_status": 200, "vmc_content_type": "application/x-pem-file", "vmc_certificate_valid": true, "vmc_subject": "/CN=Example Inc VMC", "vmc_issuer": "/CN=Example Issuer", "vmc_not_before": "2026-01-01T00:00:00Z", "vmc_not_after": "2027-01-01T00:00:00Z", "vmc_days_to_expiry": 258, "vmc_fingerprint_sha256": "AA:BB:CC:DD", "vmc_san_domains": [ "google.com" ], "errors": [] }, "dmarc": { "record": "v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com", "tags": { "v": "DMARC1", "p": "reject", "rua": "mailto:mailauth-reports@google.com" } }, "mta_sts": { "exists": true, "record": "v=STSv1; id=2024010101Z", "valid": true, "policy_id": "2024010101Z", "policy_fetch_ok": true, "policy_http_status": 200, "mode": "enforce", "max_age": 86400, "mx_hosts": [ "*.google.com" ], "mx_records": [ "aspmx.l.google.com" ], "policy_matches_mx": true, "uncovered_mx": [], "errors": [] }, "tls_rpt": { "exists": true, "record": "v=TLSRPTv1; rua=mailto:sts-reports@google.com", "valid": true, "rua": [ "mailto:sts-reports@google.com" ], "errors": [] }, "client_access": { "provider_hint": { "id": "google_workspace", "name": "Google Workspace" }, "mx_records": [ "aspmx.l.google.com" ], "services": [ { "service": "imap", "host": "imap.gmail.com", "port": 993, "source": "provider_default", "priority": null, "weight": null, "tls_mode": "implicit", "reachable": true, "tls_negotiated": true, "starttls_offered": null, "protocol": "TLSv1.3", "cipher": "TLS_AES_256_GCM_SHA384", "certificate": { "subject": "/CN=imap.gmail.com", "issuer": "/CN=WR2", "not_before": "2026-01-01T00:00:00Z", "not_after": "2026-07-01T00:00:00Z", "days_to_expiry": 70, "expired": false, "san_domains": [ "imap.gmail.com" ], "public_key_type": "EC", "public_key_bits": 256, "fingerprint_sha256": "CC:DD:EE:FF", "hostname_match": true, "chain_valid": true, "chain_error": null }, "chain_depth": 2, "error": null } ], "reachable_service_count": 1, "secure_service_count": 1 }, "autodiscover": { "provider_hint": { "id": "google_workspace", "name": "Google Workspace" }, "mx_records": [ "aspmx.l.google.com" ], "srv": { "autodiscover": [], "submission": [], "submissions": [], "imap": [], "imaps": [], "pop3": [], "pop3s": [] }, "thunderbird_autoconfig": { "subdomain": { "url": "https://autoconfig.google.com/mail/config-v1.1.xml?emailaddress=postmaster%40google.com", "status_code": 404, "content_type": "text/html", "final_url": "https://autoconfig.google.com/mail/config-v1.1.xml?emailaddress=postmaster%40google.com", "redirect_count": 0, "incoming": [], "outgoing": [], "error": null }, "well_known": { "url": "https://google.com/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=postmaster%40google.com", "status_code": 200, "content_type": "application/xml", "final_url": "https://google.com/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=postmaster%40google.com", "redirect_count": 0, "incoming": [ { "type": "imap", "hostname": "imap.gmail.com", "port": 993, "socket_type": "SSL" } ], "outgoing": [ { "type": "smtp", "hostname": "smtp.gmail.com", "port": 587, "socket_type": "STARTTLS" } ], "error": null } }, "outlook_autodiscover": { "url": "https://autodiscover.google.com/autodiscover/autodiscover.xml", "status_code": 401, "content_type": "text/html", "final_url": "https://autodiscover.google.com/autodiscover/autodiscover.xml", "redirect_count": 0, "auth_required": true, "error": null }, "recommended": [ { "service": "imap", "host": "imap.gmail.com", "port": 993, "tls_mode": "implicit", "source": "provider_default" } ] }, "edge_summary": { "relay_configured": true, "evidence_sources": [ "spf_walk", "mail_policies", "bimi_audit", "dkim_audit", "mail_client_access", "mail_autodiscover" ], "spf_lookup_count": 1, "spf_lookup_limit_exceeded": false, "dkim_valid_selector_count": 1, "dkim_weak_selector_count": 0, "dkim_revoked_selector_count": 0, "providers_detected": [ "Google Workspace" ], "mta_sts_enforced": true, "tls_rpt_configured": true, "bimi_logo_verified": true, "vmc_certificate_valid": true, "client_access_reachable_services": 1, "client_access_secure_services": 1, "autodiscover_recommendation_count": 1 }, "provider_selector_recommendations": [ { "provider": "Google Workspace", "selectors": [ "google", "20230601", "20210112" ], "source": "detected", "checked_selectors": [ "google" ], "found_selectors": [ "google" ], "missing_selectors": [ "20230601", "20210112" ] } ], "grade": "A", "notes": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/email-auth/bulk` Operation: `bulkGetEmailAuth` Credits and authentication: 3 Authentication required POST /v1/email-auth/bulk Credits: 3/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | | selectors | string[] | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/email-auth/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "cloudflare.com" ], "selectors": [ "selector1", "selector2" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/email-auth/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "cloudflare.com" ], "selectors": [ "selector1", "selector2" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/email-auth/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "cloudflare.com", ], "selectors": [ "selector1", "selector2", ], }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "domains": [ "example.com", "cloudflare.com" ], "selectors": [ "selector1", "selector2" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/email-auth/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email-auth/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "cloudflare.com" ], "selectors" => [ "selector1", "selector2" ] }) #### Example response ```json { "results": [ { "input": "example", "data": {} } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "max_items": 10, "credits_per_item": 1, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## POST `/v1/tools/spf/build` Operation: `buildSpf` Credits and authentication: 1 Authentication required POST /v1/tools/spf/build Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | include | string[] | optional | | ip4 | string[] | optional | | ip6 | string[] | optional | | a | boolean | optional | | mx | boolean | optional | | redirect | string | optional | | all | string Allowed values `pass`, `fail`, `softfail`, `neutral` | required | #### Response fields | Field | Type | | --- | --- | | `record` | string | | `dns_name` | string | | `record_type` | string | | `length` | integer | | `dns_lookups` | integer | | `valid` | boolean | | `warnings[]` | string[] | | `explanation` | object | #### Example request ```bash curl -X POST "https://domscan.net/v1/tools/spf/build" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "include": [ "_spf.google.com" ], "ip4": [ "192.0.2.0/24" ], "mx": true, "all": "softfail" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/spf/build", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "include": [ "_spf.google.com" ], "ip4": [ "192.0.2.0/24" ], "mx": true, "all": "softfail" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tools/spf/build", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "include": [ "_spf.google.com", ], "ip4": [ "192.0.2.0/24", ], "mx": True, "all": "softfail", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "include": [ "_spf.google.com" ], "ip4": [ "192.0.2.0/24" ], "mx": true, "all": "softfail" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tools/spf/build", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/spf/build") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "include" => [ "_spf.google.com" ], "ip4" => [ "192.0.2.0/24" ], "mx" => true, "all" => "softfail" }) #### Example response ```json { "record": "example", "dns_name": "example", "record_type": "domain", "length": 1, "dns_lookups": 1, "valid": true, "warnings": [ "example" ], "explanation": {} } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## POST `/v1/tools/spf/validate` Operation: `validateSpf` Credits and authentication: 1 Authentication required POST /v1/tools/spf/validate Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | record | string | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `record` | string \| null | | `valid` | boolean | | `version` | string \| null | | `mechanisms[]` | object[] | | `mechanisms[]` | object | | `mechanisms[].qualifier` | string | | `mechanisms[].mechanism` | string | | `mechanisms[].value` | string | | `mechanisms[].description` | string | | `dns_lookups` | integer | | `max_lookups` | integer | | `lookup_limit_exceeded` | boolean | | `policy` | string \| null | | `includes[]` | string[] | | `ips[]` | string[] | | `issues[]` | string[] | | `warnings[]` | string[] | | `error` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/tools/spf/validate" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domain": "example.com", "record": "v=spf1 include:_spf.google.com ip4:192.0.2.0/24 ~all" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/spf/validate", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domain": "example.com", "record": "v=spf1 include:_spf.google.com ip4:192.0.2.0/24 ~all" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tools/spf/validate", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domain": "example.com", "record": "v=spf1 include:_spf.google.com ip4:192.0.2.0/24 ~all", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "domain": "example.com", "record": "v=spf1 include:_spf.google.com ip4:192.0.2.0/24 ~all" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tools/spf/validate", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/spf/validate") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domain" => "example.com", "record" => "v=spf1 include:_spf.google.com ip4:192.0.2.0/24 ~all" }) #### Example response ```json { "domain": "example.com", "record": "v=spf1 include:_spf.google.com ip4:192.0.2.0/24 ~all", "valid": true, "version": "spf1", "mechanisms": [ { "qualifier": "+", "mechanism": "include", "value": "_spf.google.com", "description": "Include SPF from _spf.google.com" }, { "qualifier": "+", "mechanism": "ip4", "value": "192.0.2.0/24", "description": "IPv4 address/range 192.0.2.0/24" }, { "qualifier": "~", "mechanism": "all", "description": "Default policy: softfail" } ], "dns_lookups": 1, "max_lookups": 10, "lookup_limit_exceeded": false, "policy": "softfail", "includes": [ "_spf.google.com" ], "ips": [ "192.0.2.0/24" ], "issues": [], "warnings": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## POST `/v1/tools/spf/flatten` Operation: `flattenSpf` Credits and authentication: 2 Authentication required POST /v1/tools/spf/flatten Credits: 2 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `original_record` | string | | `flattened_record` | string | | `original_lookups` | integer | | `flattened_lookups` | integer | | `resolved_ips` | object | | `resolved_ips.ip4[]` | string[] | | `resolved_ips.ip6[]` | string[] | | `includes_resolved[]` | object[] | | `includes_resolved[]` | object | | `includes_resolved[].include` | string | | `includes_resolved[].resolved_to[]` | string[] | | `warnings[]` | string[] | #### Example request ```bash curl -X POST "https://domscan.net/v1/tools/spf/flatten" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domain": "example.com" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/spf/flatten", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domain": "example.com" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tools/spf/flatten", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domain": "example.com", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "domain": "example.com" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tools/spf/flatten", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/spf/flatten") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domain" => "example.com" }) #### Example response ```json { "domain": "example.com", "original_record": "example", "flattened_record": "example", "original_lookups": 1, "flattened_lookups": 1, "resolved_ips": { "ip4": [ "192.0.2.0/24" ], "ip6": [ "2001:db8::/32" ] }, "includes_resolved": [ { "include": "example", "resolved_to": [ "example" ] } ], "warnings": [ "example" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## POST `/v1/tools/dmarc/build` Operation: `buildDmarc` Credits and authentication: 1 Authentication required POST /v1/tools/dmarc/build Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | policy | string Allowed values `none`, `quarantine`, `reject` | required | | subdomain_policy | string Allowed values `none`, `quarantine`, `reject` | optional | | percentage | integer | optional | | rua | string[] | optional | | ruf | string[] | optional | | adkim | string Allowed values `relaxed`, `strict` | optional | | aspf | string Allowed values `relaxed`, `strict` | optional | #### Response fields | Field | Type | | --- | --- | | `record` | string | | `dns_name` | string | | `record_type` | string | | `valid` | boolean | | `explanation` | object | #### Example request ```bash curl -X POST "https://domscan.net/v1/tools/dmarc/build" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "policy": "quarantine", "subdomain_policy": "quarantine", "percentage": 100, "rua": [ "mailto:dmarc@example.com" ], "adkim": "relaxed", "aspf": "relaxed" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/dmarc/build", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "policy": "quarantine", "subdomain_policy": "quarantine", "percentage": 100, "rua": [ "mailto:dmarc@example.com" ], "adkim": "relaxed", "aspf": "relaxed" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tools/dmarc/build", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "policy": "quarantine", "subdomain_policy": "quarantine", "percentage": 100, "rua": [ "mailto:dmarc@example.com", ], "adkim": "relaxed", "aspf": "relaxed", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "policy": "quarantine", "subdomain_policy": "quarantine", "percentage": 100, "rua": [ "mailto:dmarc@example.com" ], "adkim": "relaxed", "aspf": "relaxed" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tools/dmarc/build", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/dmarc/build") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "policy" => "quarantine", "subdomain_policy" => "quarantine", "percentage" => 100, "rua" => [ "mailto:dmarc@example.com" ], "adkim" => "relaxed", "aspf" => "relaxed" }) #### Example response ```json { "record": "example", "dns_name": "example", "record_type": "domain", "valid": true, "explanation": {} } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## POST `/v1/tools/dmarc/validate` Operation: `validateDmarc` Credits and authentication: 1 Authentication required POST /v1/tools/dmarc/validate Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | record | string | optional | | domain | string | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `record` | string \| null | | `valid` | boolean | | `version` | string \| null | | `policy` | string \| null | | `subdomain_policy` | string \| null | | `percentage` | integer | | `rua[]` | string[] | | `ruf[]` | string[] | | `adkim` | string | | `aspf` | string | | `fo` | string | | `ri` | integer | | `strength` | string | | `issues[]` | string[] | | `warnings[]` | string[] | | `error` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/tools/dmarc/validate" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domain": "example.com", "record": "v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/dmarc/validate", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domain": "example.com", "record": "v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/tools/dmarc/validate", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domain": "example.com", "record": "v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com", }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domain": "example.com", "record": "v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/tools/dmarc/validate", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/dmarc/validate") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domain" => "example.com", "record" => "v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com" }) #### Example response ```json { "domain": "example.com", "record": "v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com; ruf=mailto:forensics@example.com", "valid": true, "version": "DMARC1", "policy": "quarantine", "subdomain_policy": null, "percentage": 50, "rua": [ "mailto:dmarc@example.com" ], "ruf": [ "mailto:forensics@example.com" ], "adkim": "relaxed", "aspf": "relaxed", "fo": "0", "ri": 86400, "strength": "weak", "issues": [], "warnings": [ "DMARC only applies to 50% of messages" ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/tools/dkim/check` Operation: `checkDkim` Credits and authentication: 1 Authentication required GET /v1/tools/dkim/check Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | selector | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `selector` | string | | `dns_name` | string | | `exists` | boolean | | `valid` | boolean | | `record` | string | | `version` | string | | `key_type` | string | | `key_data` | string | | `key_size` | integer | | `flags[]` | string[] | | `hash_algorithms[]` | string[] | | `service_type` | string | | `issues[]` | string[] | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tools/dkim/check?domain=example.com&selector=google" ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/dkim/check?domain=example.com&selector=google", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tools/dkim/check?domain=example.com&selector=google", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tools/dkim/check?domain=example.com&selector=google", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/dkim/check?domain=example.com&selector=google") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "example.com", "selector": "s1", "dns_name": "s1._domainkey.example.com", "exists": true, "valid": true, "record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmJozfC9DIeQ/D61fUDgQO/UpGyaMcxSRagnXuEbbwljO4pJcrtPIJyYW7Y8dmX3XZh1V+tvL7zhYPAYHhJ2//YGSetg20T1xvyy1s4Mfa3JPKFNvq+HYe2/ag/rz8Cl7I0rn7ET0BQc/iKxiptIlgALWdYBNiQBsLCBRsGjQWzzQh1puVIm2U+LTp9qQq42DVnkTJ/kOT2z2QjYTkGeCU19sjXi04gQu5XV7iXF7IZjLbMxE4OnUWRwlAr4n0H/PRGfuteB5KF/COZZ9fP0HKpIUjF8k5YJsjbKEiPA2sL/vKS90nsvPrWsDguT8mAPxIc2wrvYCDtL/O2fJTMQlwQIDAQAB", "version": "DKIM1", "key_type": "rsa", "key_data": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmJozfC9DIeQ/D61fUDgQO/UpGyaMcxSRagnXuEbbwljO4pJcrtPIJyYW7Y8dmX3XZh1V+tvL7zhYPAYHhJ2//YGSetg20T1xvyy1s4Mfa3JPKFNvq+HYe2/ag/rz8Cl7I0rn7ET0BQc/iKxiptIlgALWdYBNiQBsLCBRsGjQWzzQh1puVIm2U+LTp9qQq42DVnkTJ/kOT2z2QjYTkGeCU19sjXi04gQu5XV7iXF7IZjLbMxE4OnUWRwlAr4n0H/PRGfuteB5KF/COZZ9fP0HKpIUjF8k5YJsjbKEiPA2sL/vKS90nsvPrWsDguT8mAPxIc2wrvYCDtL/O2fJTMQlwQIDAQAB", "key_size": 2048, "issues": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/tools/dkim/discover` Operation: `discoverDkim` Credits and authentication: 2 Authentication required GET /v1/tools/dkim/discover Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `selectors_checked[]` | string[] | | `selectors_found[]` | object[] | | `selectors_found[]` | object | | `selectors_found[].selector` | string | | `selectors_found[].dns_name` | string | | `selectors_found[].exists` | boolean | | `selectors_found[].record` | string \| null | | `selectors_found[].record_type` | string \| null | | `selectors_found[].cname_targets[]` | string[] | | `selectors_found[].key_type` | string \| null | | `selectors_found[].key_size` | integer \| null | | `selectors_found[].provider_hint` | string \| null | | `selectors_found[].valid` | boolean | | `selectors_found[].revoked` | boolean | | `selectors_found[].weak` | boolean | | `selectors_found[].hash_algorithms[]` | string[] | | `selectors_found[].service_type` | string \| null | | `selectors_found[].flags[]` | string[] | | `selectors_found[].issues[]` | string[] | | `total_found` | integer | | `common_providers_detected[]` | string[] | | `providers_detected[]` | string[] | | `valid_selector_count` | integer | | `weak_selector_count` | integer | | `revoked_selector_count` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/tools/dkim/discover?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/tools/dkim/discover?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/tools/dkim/discover?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/tools/dkim/discover?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/tools/dkim/discover?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "selectors_checked": [ "example" ], "selectors_found": [ { "selector": "default", "dns_name": "example", "exists": true, "record": "example", "record_type": "TXT", "cname_targets": [ "example" ], "key_type": "domain", "key_size": 1, "provider_hint": "example", "valid": true, "revoked": false, "weak": false, "hash_algorithms": [ "example" ], "service_type": "domain", "flags": [ "example" ], "issues": [ "example" ] } ], "total_found": 1, "common_providers_detected": [ "example" ], "providers_detected": [ "example" ], "valid_selector_count": 1, "weak_selector_count": 1, "revoked_selector_count": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/email-compliance # Email Compliance API Analyze email authentication records including SPF, DKIM, and DMARC. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/email-compliance-api) ## Operations GET `/v1/email/compliance` [View API reference](https://domscan.net/docs/products/email-compliance#getEmailCompliance) ## GET `/v1/email/compliance` Operation: `getEmailCompliance` Credits and authentication: 6 Authentication required GET /v1/email/compliance Credits: 6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | selectors | string | optional | | providers | string | optional | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `status` | string | | `score` | integer | | `grade` | string | | `provider_readiness` | object | | `provider_readiness.google` | object | | `provider_readiness.google.provider` | string | | `provider_readiness.google.display_name` | string | | `provider_readiness.google.status` | string | | `provider_readiness.google.dns_visible_status` | string | | `provider_readiness.google.requirements[]` | object[] | | `provider_readiness.google.requirements[]` | object | | `provider_readiness.google.requirements[].id` | string | | `provider_readiness.google.requirements[].label` | string | | `provider_readiness.google.requirements[].status` | string | | `provider_readiness.google.requirements[].severity` | string | | `provider_readiness.google.requirements[].category` | string | | `provider_readiness.google.requirements[].evidence` | string | | `provider_readiness.google.requirements[].recommendation` | string | | `provider_readiness.google.verification_required[]` | string[] | | `provider_readiness.google.notes[]` | string[] | | `provider_readiness.microsoft` | object | | `provider_readiness.microsoft.provider` | string | | `provider_readiness.microsoft.display_name` | string | | `provider_readiness.microsoft.status` | string | | `provider_readiness.microsoft.dns_visible_status` | string | | `provider_readiness.microsoft.requirements[]` | object[] | | `provider_readiness.microsoft.requirements[]` | object | | `provider_readiness.microsoft.requirements[].id` | string | | `provider_readiness.microsoft.requirements[].label` | string | | `provider_readiness.microsoft.requirements[].status` | string | | `provider_readiness.microsoft.requirements[].severity` | string | | `provider_readiness.microsoft.requirements[].category` | string | | `provider_readiness.microsoft.requirements[].evidence` | string | | `provider_readiness.microsoft.requirements[].recommendation` | string | | `provider_readiness.microsoft.verification_required[]` | string[] | | `provider_readiness.microsoft.notes[]` | string[] | | `summary` | object | | `summary.authentication` | object | | `summary.transport` | object | | `summary.dns_security` | object | | `summary.brand_trust` | object | | `action_items[]` | object[] | | `action_items[]` | object | | `action_items[].priority` | string | | `action_items[].category` | string | | `action_items[].title` | string | | `action_items[].detail` | string | | `action_items[].fix` | string | | `evidence` | object | | `evidence.email_auth` | object | | `evidence.dns_security` | object | | `proxy` | object | | `proxy.configured` | boolean | | `proxy.enriched` | boolean | | `proxy.checks[]` | string[] | | `limitations[]` | string[] | | `checked_at` | string | | `check_duration_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/email/compliance?domain=example.com&selectors=google%2Cselector1%2Csendgrid&providers=google%2Cmicrosoft" ``` ```javascript const response = await fetch("https://domscan.net/v1/email/compliance?domain=example.com&selectors=google%2Cselector1%2Csendgrid&providers=google%2Cmicrosoft", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/email/compliance?domain=example.com&selectors=google%2Cselector1%2Csendgrid&providers=google%2Cmicrosoft", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/email/compliance?domain=example.com&selectors=google%2Cselector1%2Csendgrid&providers=google%2Cmicrosoft", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/compliance?domain=example.com&selectors=google%2Cselector1%2Csendgrid&providers=google%2Cmicrosoft") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "status": "warn", "score": 82, "grade": "B", "provider_readiness": { "google": { "provider": "google", "display_name": "Google/Gmail bulk sender readiness", "status": "pass", "dns_visible_status": "pass", "requirements": [ { "id": "google_spf", "label": "SPF must be configured for bulk senders", "status": "pass", "severity": "critical", "category": "dns", "evidence": "SPF policy: softfail", "recommendation": "Publish one valid SPF record that covers every approved sending platform." }, { "id": "google_alignment", "label": "From domain must align with either SPF or DKIM on live messages", "status": "unknown", "severity": "high", "category": "message", "evidence": "Alignment requires Authentication-Results from a real sent message", "recommendation": "Send a test message and verify SPF or DKIM alignment." } ], "verification_required": [ "From domain must align with either SPF or DKIM on live messages", "Outbound mail must be transmitted over TLS" ], "notes": [ "Status is based on DNS-visible controls. Live sending requirements still need message-header and sender-platform verification." ] }, "microsoft": { "provider": "microsoft", "display_name": "Microsoft Outlook.com high-volume sender readiness", "status": "pass", "dns_visible_status": "pass", "requirements": [], "verification_required": [ "DMARC must align with either SPF or DKIM" ], "notes": [ "Status is based on DNS-visible controls. Live sending requirements still need message-header and sender-platform verification." ] } }, "summary": { "authentication": { "spf": { "status": "pass", "record": "v=spf1 include:_spf.example.com ~all", "policy": "softfail", "lookup_count": 3, "lookup_limit_exceeded": false }, "dkim": { "status": "pass", "selectors_checked": [ "google", "selector1", "sendgrid" ], "selectors_found": [ "google" ], "valid_selector_count": 1, "weak_selector_count": 0, "revoked_selector_count": 0, "providers_detected": [ "Google Workspace" ] }, "dmarc": { "status": "warn", "record": "v=DMARC1; p=none; rua=mailto:dmarc@example.com", "policy": "none", "subdomain_policy": null, "percentage": 100, "rua": [ "mailto:dmarc@example.com" ], "alignment_mode": { "spf": null, "dkim": null } } }, "transport": { "mta_sts": { "status": "pass", "mode": "enforce", "policy_fetch_ok": true, "policy_matches_mx": true }, "tls_rpt": { "status": "pass", "rua": [ "mailto:tls@example.com" ] }, "mx_records": [ "aspmx.l.google.com" ], "client_access_secure_services": 1 }, "dns_security": { "dnssec": "pass", "caa": "pass", "zone_transfer": "pass", "authoritative_consistency": "pass", "blacklist": "pass" }, "brand_trust": { "bimi": "unknown", "vmc": "unknown" } }, "action_items": [ { "priority": "medium", "category": "authentication", "title": "Move DMARC beyond monitoring mode", "detail": "DMARC is valid but still uses p=none.", "fix": "After reviewing aggregate reports, move to p=quarantine or p=reject." } ], "evidence": { "email_auth": { "spf": { "record": "v=spf1 include:_spf.example.com ~all" }, "dmarc": { "record": "v=DMARC1; p=none; rua=mailto:dmarc@example.com" } }, "dns_security": { "security_score": 86, "security_grade": "B" } }, "proxy": { "configured": true, "enriched": true, "checks": [ "spf_walk", "mail_policies", "dkim_audit", "bimi_audit" ] }, "limitations": [ "DNS-visible checks cannot prove live message-level SPF, DKIM, DMARC alignment, RFC 5322 formatting, spam rate, or one-click unsubscribe behavior." ], "checked_at": "2026-04-26T12:00:00Z", "check_duration_ms": 642 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/email-blacklist # Email Blacklist API Check if a domain or IP is listed on email blacklists. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/email-blacklist-api) ## Operations GET `/v1/email/check` [View API reference](https://domscan.net/docs/products/email-blacklist#checkEmailBlacklist) POST `/v1/email/check/bulk` [View API reference](https://domscan.net/docs/products/email-blacklist#bulkEmailCheck) GET `/v1/email/blacklist` [View API reference](https://domscan.net/docs/products/email-blacklist#getEmailBlacklistInfo) GET `/v1/email/blacklist/download` [View API reference](https://domscan.net/docs/products/email-blacklist#downloadEmailBlacklist) ## GET `/v1/email/check` Operation: `checkEmailBlacklist` Credits and authentication: 1 Authentication required GET /v1/email/check Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | email | string | required | | checks | string | optional | #### Response fields | Field | Type | | --- | --- | | `email` | string | | `domain` | string | | `local_part` | string | | `valid_syntax` | boolean | | `checks` | object | | `checks.disposable` | object | | `checks.disposable.is_disposable` | boolean | | `checks.disposable.confidence` | string \| null | | `checks.disposable.matched_pattern` | string | | `checks.role` | object | | `checks.role.is_role` | boolean | | `checks.role.role_type` | string \| null | | `checks.free` | object | | `checks.free.is_free` | boolean | | `checks.free.provider` | string \| null | | `checks.mx` | object | | `checks.mx.has_mx` | boolean | | `checks.mx.records[]` | string[] | | `checks.mx.null_mx` | boolean | | `checks.dnsbl` | object | | `checks.dnsbl.domain` | string | | `checks.dnsbl.ip` | string | | `checks.dnsbl.listed` | boolean | | `checks.dnsbl.lists[]` | object[] | | `checks.dnsbl.lists[]` | object | | `checks.dnsbl.lists[].name` | string | | `checks.dnsbl.lists[].listed` | boolean | | `checks.dnsbl.lists[].code` | string | | `checks.dnsbl.lists[].meaning` | string | | `checks.dnsbl.threat_level` | string | | `checks.dnsbl.check_type` | string | | `checks.dnsbl.checked_at` | string | | `risk_score` | integer | | `risk_level` | string | | `flags[]` | string[] | | `checked_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/email/check?email=user%40example.com&checks=disposable%2Crole%2Cfree%2Cmx%2Cdnsbl" ``` ```javascript const response = await fetch("https://domscan.net/v1/email/check?email=user%40example.com&checks=disposable%2Crole%2Cfree%2Cmx%2Cdnsbl", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/email/check?email=user%40example.com&checks=disposable%2Crole%2Cfree%2Cmx%2Cdnsbl", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/email/check?email=user%40example.com&checks=disposable%2Crole%2Cfree%2Cmx%2Cdnsbl", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/check?email=user%40example.com&checks=disposable%2Crole%2Cfree%2Cmx%2Cdnsbl") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "email": "support@acme-widgets.com", "domain": "acme-widgets.com", "local_part": "support", "valid_syntax": true, "checks": { "disposable": { "is_disposable": false, "confidence": null }, "role": { "is_role": true, "role_type": "support" }, "free": { "is_free": false, "provider": null }, "mx": { "has_mx": true, "records": [ "mx1.mailhost-example.net", "mx2.mailhost-example.net" ] }, "dnsbl": { "listed": false, "threat_level": "none" } }, "risk_score": 20, "risk_level": "low", "flags": [ "ROLE_ADDRESS" ], "checked_at": "2026-10-09T10:15:30.000Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/email/check/bulk` Operation: `bulkEmailCheck` Credits and authentication: 1 Authentication required POST /v1/email/check/bulk Credits: 1/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | emails | string[] | required | | checks | string[] Allowed values `disposable`, `role`, `free`, `mx`, `dnsbl` | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `summary` | object | | `summary.total` | integer | | `summary.disposable` | integer | | `summary.role_based` | integer | | `summary.free_provider` | integer | | `summary.no_mx` | integer | | `summary.dnsbl_listed` | integer | | `summary.high_risk` | integer | | `summary.medium_risk` | integer | | `summary.low_risk` | integer | | `checked_at` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/email/check/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "emails": [ "jane.doe@example.com", "support@example.org" ], "checks": [ "disposable", "role", "mx" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/email/check/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "emails": [ "jane.doe@example.com", "support@example.org" ], "checks": [ "disposable", "role", "mx" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/email/check/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "emails": [ "jane.doe@example.com", "support@example.org", ], "checks": [ "disposable", "role", "mx", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "emails": [ "jane.doe@example.com", "support@example.org" ], "checks": [ "disposable", "role", "mx" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/email/check/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/check/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "emails" => [ "jane.doe@example.com", "support@example.org" ], "checks" => [ "disposable", "role", "mx" ] }) #### Example response ```json { "results": [ {} ], "summary": { "total": 10, "disposable": 3, "role_based": 1, "free_provider": 2, "no_mx": 0, "dnsbl_listed": 0, "high_risk": 3, "medium_risk": 1, "low_risk": 6 }, "checked_at": "2026-08-27T12:00:00Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/email/blacklist` Operation: `getEmailBlacklistInfo` Credits and authentication: Free Authentication required GET /v1/email/blacklist Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer Default `1000` | optional | | offset | integer Default `0` | optional | | format | string Allowed values `json`, `txt` Default `json` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `domains[]` | string[] | | `total` | integer | | `offset` | integer | | `limit` | integer | | `metadata` | object | | `metadata.last_updated` | string | | `metadata.total_domains` | integer | | `metadata.high_confidence_count` | integer | | `metadata.wildcard_count` | integer | | `metadata.sources[]` | string[] | | `metadata.source_count` | integer | | `metadata.successful_source_count` | integer | | `metadata.failed_source_count` | integer | | `metadata.refresh_cadence_hours` | integer | | `metadata.refresh_status` | string | | `metadata.next_refresh_due` | string | | `metadata.dataset_status` | string | | `metadata.quality_policy_version` | integer \| null | | `metadata.quarantined_domain_count` | integer | | `metadata.rejected_domain_count` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/email/blacklist?limit=25&offset=0&format=json" ``` ```javascript const response = await fetch("https://domscan.net/v1/email/blacklist?limit=25&offset=0&format=json", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/email/blacklist?limit=25&offset=0&format=json", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/email/blacklist?limit=25&offset=0&format=json", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/blacklist?limit=25&offset=0&format=json") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domains": [ "0-00.usa.cc", "0-180.com", "0-30-24.com" ], "total": 91331, "offset": 0, "limit": 3, "metadata": { "last_updated": "2026-10-09T03:00:07.499Z", "total_domains": 91331, "high_confidence_count": 5142, "wildcard_count": 0, "sources": [ "disposable-email-domains", "fakefilter", "mailchecker" ], "source_count": 8, "successful_source_count": 8, "failed_source_count": 0, "refresh_cadence_hours": 24, "refresh_status": "fresh", "next_refresh_due": "2026-10-10T03:00:07.499Z", "dataset_status": "complete", "quality_policy_version": 2, "quarantined_domain_count": 0, "rejected_domain_count": 0 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `429` Too Many Requests ## GET `/v1/email/blacklist/download` Operation: `downloadEmailBlacklist` Credits and authentication: Free Authentication required GET /v1/email/blacklist/download Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | format | string Allowed values `json`, `txt` Default `json` | optional | #### Response fields | Field | Type | | --- | --- | | `domains[]` | string[] | | `wildcards[]` | string[] | | `metadata` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/email/blacklist/download?format=json" ``` ```javascript const response = await fetch("https://domscan.net/v1/email/blacklist/download?format=json", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/email/blacklist/download?format=json", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/email/blacklist/download?format=json", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/blacklist/download?format=json") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domains": [ "example.com", "example.org" ], "wildcards": [ "example" ], "metadata": {} } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/social-handles # Social Handle Availability API Check if a username is available across major social media platforms. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/social-handle-checker) ## Operations GET `/v1/social` [View API reference](https://domscan.net/docs/products/social-handles#checkSocialHandles) POST `/v1/social/bulk` [View API reference](https://domscan.net/docs/products/social-handles#bulkCheckSocialHandles) GET `/v1/social/info` [View API reference](https://domscan.net/docs/products/social-handles#getSocialInfo) ## GET `/v1/social` Operation: `checkSocialHandles` Credits and authentication: 2 Authentication required GET /v1/social Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | handle | string | required | | platforms | string | optional | | resources | string | optional | #### Response fields | Field | Type | | --- | --- | | `handle` | string | | `checked_at` | string | | `availability` | object | | `resources` | object | | `resource_summary` | object | | `resource_summary.requested_count` | integer | | `resource_summary.checked_count` | integer | | `resource_summary.present_count` | integer | | `resource_summary.absent_count` | integer | | `resource_summary.unknown_count` | integer | | `resource_summary.cached_count` | integer | | `resource_summary.determinacy_rate` | number | | `summary` | object | | `summary.available_count` | integer | | `summary.unavailable_count` | integer | | `summary.unknown_count` | integer | | `summary_v2` | object | | `summary_v2.requested_count` | integer | | `summary_v2.checked_count` | integer | | `summary_v2.available_count` | integer | | `summary_v2.unavailable_count` | integer | | `summary_v2.unknown_count` | integer | | `summary_v2.not_supported_count` | integer | | `summary_v2.determinacy_rate` | number | | `platform_summary` | object | | `platform_summary.requested_count` | integer | | `platform_summary.checked_count` | integer | | `platform_summary.available_count` | integer | | `platform_summary.unavailable_count` | integer | | `platform_summary.unknown_count` | integer | | `platform_summary.not_supported_count` | integer | | `platform_summary.cached_count` | integer | | `platform_summary.high_confidence_count` | integer | | `platform_summary.live_platform_count` | integer | | `platform_summary.experimental_count` | integer | | `platform_summary.blocked_count` | integer | | `platform_summary.beta_limited_count` | integer | | `platform_summary.determinacy_rate` | number | | `platform_summary.method_counts` | object | | `platform_summary.source_counts` | object | | `beta_notice` | string | | `meta` | object | | `meta.served_by` | string | | `meta.supported_platforms[]` | string[] | | `meta.supported_resources[]` | string[] | | `meta.unsupported_platforms[]` | string[] | | `meta.latency_ms` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/social?handle=myusername&platforms=github%2Cgitlab%2Cbitbucket%2Cdevto%2Chuggingface%2Cdribbble%2Csoundcloud%2Cgumroad%2Cbuymeacoffee%2Csubstack%2Citchio%2Chackernews%2Creddit%2Cbluesky%2Cpatreon%2Csnapchat%2Cyoutube&resources=github%3Arepository" ``` ```javascript const response = await fetch("https://domscan.net/v1/social?handle=myusername&platforms=github%2Cgitlab%2Cbitbucket%2Cdevto%2Chuggingface%2Cdribbble%2Csoundcloud%2Cgumroad%2Cbuymeacoffee%2Csubstack%2Citchio%2Chackernews%2Creddit%2Cbluesky%2Cpatreon%2Csnapchat%2Cyoutube&resources=github%3Arepository", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/social?handle=myusername&platforms=github%2Cgitlab%2Cbitbucket%2Cdevto%2Chuggingface%2Cdribbble%2Csoundcloud%2Cgumroad%2Cbuymeacoffee%2Csubstack%2Citchio%2Chackernews%2Creddit%2Cbluesky%2Cpatreon%2Csnapchat%2Cyoutube&resources=github%3Arepository", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/social?handle=myusername&platforms=github%2Cgitlab%2Cbitbucket%2Cdevto%2Chuggingface%2Cdribbble%2Csoundcloud%2Cgumroad%2Cbuymeacoffee%2Csubstack%2Citchio%2Chackernews%2Creddit%2Cbluesky%2Cpatreon%2Csnapchat%2Cyoutube&resources=github%3Arepository", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/social?handle=myusername&platforms=github%2Cgitlab%2Cbitbucket%2Cdevto%2Chuggingface%2Cdribbble%2Csoundcloud%2Cgumroad%2Cbuymeacoffee%2Csubstack%2Citchio%2Chackernews%2Creddit%2Cbluesky%2Cpatreon%2Csnapchat%2Cyoutube&resources=github%3Arepository") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "handle": "examplebrand", "checked_at": "2026-10-09T10:15:30.000Z", "availability": { "github": { "available": true, "profile_url": null, "checked": true, "method": "official_api", "confidence": "high", "latency_ms": 112, "evidence": { "source": "upstream" }, "requested": true }, "gitlab": { "available": false, "profile_url": "https://gitlab.com/examplebrand", "checked": true, "entity_type": "user", "canonical_handle": "examplebrand", "visibility": "public", "method": "official_api", "confidence": "high", "latency_ms": 96, "evidence": { "source": "upstream" }, "requested": true }, "reddit": { "available": null, "profile_url": null, "checked": false, "reason": "not_requested", "method": "public_endpoint", "confidence": "high", "latency_ms": 0, "evidence": { "source": "not_requested" }, "requested": false } }, "resources": {}, "resource_summary": { "requested_count": 0, "checked_count": 0, "present_count": 0, "absent_count": 0, "unknown_count": 0, "cached_count": 0, "determinacy_rate": 0 }, "summary": { "available_count": 1, "unavailable_count": 1, "unknown_count": 34 }, "summary_v2": { "requested_count": 2, "checked_count": 2, "available_count": 1, "unavailable_count": 1, "unknown_count": 0, "not_supported_count": 0, "determinacy_rate": 1 }, "platform_summary": { "requested_count": 2, "checked_count": 2, "available_count": 1, "unavailable_count": 1, "unknown_count": 0, "not_supported_count": 0, "cached_count": 0, "high_confidence_count": 2, "live_platform_count": 2, "experimental_count": 0, "blocked_count": 0, "beta_limited_count": 0, "determinacy_rate": 1, "method_counts": { "official_api": 2 }, "source_counts": { "upstream": 2 } }, "beta_notice": "This endpoint is in beta. Supported platforms and coverage may expand as new checkers graduate to production.", "meta": { "supported_platforms": [ "github", "gitlab", "bitbucket" ], "supported_resources": [ "reddit:subreddit", "github:repository", "gitlab:project" ], "unsupported_platforms": [], "latency_ms": 412 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/social/bulk` Operation: `bulkCheckSocialHandles` Credits and authentication: 2 Authentication required POST /v1/social/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | handles | string[] | required | | platforms | string[] | optional | | resources | string[] | optional | #### Response fields | Field | Type | | --- | --- | | `results[]` | unknown[] | | `summary` | object | | `summary.total` | integer | | `summary.succeeded` | integer | | `summary.failed` | integer | | `beta_notice` | string | | `meta` | object | | `meta.served_by` | string | | `meta.platforms[]` | string[] | | `meta.resources[]` | string[] | | `meta.max_handles` | integer | | `meta.credits_per_handle` | integer | | `meta.credits_required` | integer | | `meta.latency_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/social/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "handles": [ "mycompany", "myproduct" ], "platforms": [ "github", "reddit", "youtube" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/social/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "handles": [ "mycompany", "myproduct" ], "platforms": [ "github", "reddit", "youtube" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/social/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "handles": [ "mycompany", "myproduct", ], "platforms": [ "github", "reddit", "youtube", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "handles": [ "mycompany", "myproduct" ], "platforms": [ "github", "reddit", "youtube" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/social/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/social/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "handles" => [ "mycompany", "myproduct" ], "platforms" => [ "github", "reddit", "youtube" ] }) #### Example response ```json { "results": [ { "handle": "mycompany", "availability": { "github": { "available": false, "profile_url": "https://github.com/mycompany", "checked": true, "requested": true, "method": "official_api", "confidence": "high" } }, "resources": {}, "resource_summary": { "requested_count": 0, "checked_count": 0, "present_count": 0, "absent_count": 0, "unknown_count": 0, "cached_count": 0, "determinacy_rate": 0 }, "summary": { "available_count": 0, "unavailable_count": 1, "unknown_count": 0 }, "checked_at": "2026-07-09T20:45:00.000Z" }, { "handle": "myproduct", "availability": { "github": { "available": true, "profile_url": null, "checked": true, "requested": true, "method": "official_api", "confidence": "high" } }, "resources": {}, "resource_summary": { "requested_count": 0, "checked_count": 0, "present_count": 0, "absent_count": 0, "unknown_count": 0, "cached_count": 0, "determinacy_rate": 0 }, "summary": { "available_count": 1, "unavailable_count": 0, "unknown_count": 0 }, "checked_at": "2026-07-09T20:45:00.000Z" } ], "summary": { "total": 2, "succeeded": 2, "failed": 0 }, "beta_notice": "Social handle checks are in beta; verify critical results directly.", "meta": { "served_by": "pop=MAD country=ES", "platforms": [ "github" ], "resources": [], "max_handles": 10, "credits_per_handle": 2, "credits_required": 4, "latency_ms": 420 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/social/info` Operation: `getSocialInfo` Credits and authentication: Free Authentication required GET /v1/social/info Credits: 0 #### Response fields | Field | Type | | --- | --- | | `endpoint` | string | | `description` | string | | `parameters` | object | | `bulk` | object | | `bulk.endpoint` | string | | `bulk.method` | string | | `bulk.max_handles` | integer | | `bulk.credits_per_handle` | integer | | `bulk.pricing_formula` | string | | `bulk.bulk_discount` | boolean | | `bulk.invalid_handles_charged` | boolean | | `bulk.partial_results` | boolean | | `bulk.parameters` | object | | `bulk.example_request` | object | | `platforms` | object | | `platforms.supported[]` | string[] | | `platforms.coming_soon[]` | string[] | | `platforms.experimental[]` | string[] | | `platforms.planned[]` | string[] | | `platforms.blocked[]` | string[] | | `platforms.details[]` | object[] | | `platforms.details[]` | object | | `platforms.details[].id` | string | | `platforms.details[].display_name` | string | | `platforms.details[].aliases[]` | string[] | | `platforms.details[].category` | string | | `platforms.details[].tier` | integer | | `platforms.details[].status` | string | | `platforms.details[].method` | string | | `platforms.details[].confidence` | string | | `platforms.details[].logo_key` | string | | `platforms.details[].profile_url_template` | string \| null | | `platforms.details[].docs_anchor` | string | | `platforms.details[].caveat_codes[]` | string[] | | `platforms.details[].cache_ttl_s` | object | | `platforms.details[].cache_ttl_s.available` | integer | | `platforms.details[].cache_ttl_s.taken` | integer | | `platforms.details[].cache_ttl_s.unknown` | integer | | `platforms.details[].cache_ttl_s.rate_limited` | integer | | `platforms.details[].handle_rules` | object | | `platforms.details[].handle_rules.min_length` | integer | | `platforms.details[].handle_rules.max_length` | integer | | `platforms.details[].handle_rules.description` | string | | `resource_types` | object | | `resource_types.supported[]` | string[] | | `resource_types.details[]` | object[] | | `resource_types.details[]` | object | | `example_request` | string | | `resource_example_request` | string | | `example_response` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/social/info" ``` ```javascript const response = await fetch("https://domscan.net/v1/social/info", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/social/info", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/social/info", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/social/info") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "endpoint": "/v1/social", "description": "Check if a username is available on supported social platforms.", "parameters": { "handle": { "type": "string", "required": true, "description": "Username to check" }, "platforms": { "type": "string", "required": false, "description": "Comma-separated platform list", "example": "github,gitlab,reddit" }, "resources": { "type": "string", "required": false, "description": "Comma-separated resource type list", "example": "github:repository" } }, "bulk": { "endpoint": "/v1/social/bulk", "method": "POST", "max_handles": 10, "credits_per_handle": 2, "pricing_formula": "valid_handle_count * credits_per_handle", "bulk_discount": false, "invalid_handles_charged": false, "partial_results": true, "parameters": { "handles": { "type": "array", "required": true, "min_items": 1, "max_items": 10 }, "platforms": { "type": "array", "required": false }, "resources": { "type": "array", "required": false } }, "example_request": { "handles": [ "mycompany", "myproduct" ], "platforms": [ "github", "reddit", "youtube" ] } }, "platforms": { "supported": [ "github", "gitlab", "bitbucket", "devto", "huggingface", "dribbble", "soundcloud", "gumroad", "buymeacoffee", "substack", "itchio", "behance", "dockerhub", "hashnode", "rubygems", "hackernews", "reddit", "bluesky", "twitter", "instagram", "facebook", "threads", "pinterest", "snapchat", "telegram", "twitch", "patreon", "tiktok", "youtube", "linkedin", "steam", "tumblr", "vimeo", "letterboxd", "linktree", "kick", "medium", "mastodon", "roblox", "minecraft", "chesscom", "lichess", "npm", "discord" ], "coming_soon": [], "experimental": [], "planned": [], "blocked": [], "details": [ { "id": "github", "display_name": "GitHub", "aliases": [ "github" ], "category": "developer", "tier": 0, "status": "live", "method": "official_api", "confidence": "high", "logo_key": "github", "profile_url_template": "https://github.com/{handle}", "docs_anchor": "github", "caveat_codes": [], "cache_ttl_s": { "available": 300, "taken": 3600, "unknown": 60, "rate_limited": 60 }, "handle_rules": { "min_length": 1, "max_length": 39, "description": "1-39 chars, alphanumeric and hyphens, cannot start/end with hyphen" } } ] }, "resource_types": { "supported": [ "reddit:subreddit", "discord:invite", "github:repository", "gitlab:project", "dockerhub:repository", "activitypub:account", "substack:profile" ] }, "example_request": "/v1/social?handle=myusername&platforms=github,gitlab,reddit", "resource_example_request": "/v1/social?handle=github/docs&resources=github:repository", "example_response": { "handle": "myusername", "checked_at": "2026-07-14T12:00:00Z", "availability": { "github": { "available": true, "profile_url": null, "checked": true, "requested": true }, "reddit": { "available": false, "profile_url": "https://reddit.com/user/myusername", "checked": true, "requested": true }, "gitlab": { "available": true, "profile_url": null, "checked": true, "requested": true } }, "resources": {}, "resource_summary": { "requested_count": 0, "checked_count": 0, "present_count": 0, "absent_count": 0, "unknown_count": 0, "cached_count": 0, "determinacy_rate": 0 }, "summary": { "available_count": 2, "unavailable_count": 1, "unknown_count": 0 }, "summary_v2": { "requested_count": 3, "checked_count": 3, "available_count": 2, "unavailable_count": 1, "unknown_count": 0, "not_supported_count": 0, "determinacy_rate": 1 } } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/email-verification # Email Verification API Assess email syntax, domain mail setup, disposable-address signals, and delivery risk without claiming mailbox existence. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/email-verification-api) ## Operations GET `/v1/email/verify` [View API reference](https://domscan.net/docs/products/email-verification#verifyEmail) POST `/v1/email/verify/bulk` [View API reference](https://domscan.net/docs/products/email-verification#verifyEmailBulk) ## GET `/v1/email/verify` Operation: `verifyEmail` Credits and authentication: 2 Authentication required GET /v1/email/verify Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | email | string | required | | full | boolean Default `false` | optional | #### Response fields | Field | Type | | --- | --- | | `email` | string | | `normalized_email` | string | | `result` | string | | `result_detail` | string | | `message` | string \| null | | `risk` | string | | `confidence` | number | | `confidence_level` | string | | `decision` | string | | `reasons[]` | string[] | | `verification` | object | | `verification.syntax_valid` | boolean | | `verification.mx_found` | boolean | | `verification.null_mx` | boolean | | `verification.mx_records[]` | string[] | | `verification.smtp_verified` | boolean \| null | | `verification.mailbox_exists` | boolean \| null | | `verification.catch_all` | boolean \| null | | `verification.full_inbox` | boolean \| null | | `verification.smtp_provider` | string \| null | | `classification` | object | | `classification.disposable` | boolean | | `classification.disposable_confidence` | string \| null | | `classification.role_based` | boolean | | `classification.role_type` | string \| null | | `classification.free_provider` | boolean | | `classification.provider` | string \| null | | `reputation` | object | | `reputation.dnsbl_listed` | boolean | | `reputation.threat_level` | string \| null | | `quality` | object | | `quality.score` | integer | | `quality.grade` | string | | `quality.flags[]` | string[] | | `signals` | object | | `evidence` | object | | `evidence.mx_records[]` | string[] | | `evidence.provider` | string \| null | | `evidence.checked_via[]` | string[] | | `evidence.normalized_parts` | object | | `evidence.normalized_parts.local_part` | string | | `evidence.normalized_parts.domain` | string | | `evidence.normalized_parts.base_local_part` | string | | `evidence.normalized_parts.tag` | string \| null | | `evidence.domain_profile` | object | | `evidence.domain_profile.tld` | string \| null | | `evidence.domain_profile.label_count` | integer | | `evidence.domain_profile.reserved` | boolean | | `evidence.domain_profile.domain_literal` | boolean | | `evidence.domain_profile.punycode` | boolean | | `evidence.domain_profile.suspicious_reasons[]` | string[] | | `evidence.domain_authentication` | object | | `evidence.domain_authentication.checked` | boolean | | `evidence.domain_authentication.status` | string | | `evidence.domain_authentication.spf` | object | | `evidence.domain_authentication.spf.exists` | boolean | | `evidence.domain_authentication.spf.policy` | string | | `evidence.domain_authentication.spf.record` | string \| null | | `evidence.domain_authentication.dmarc` | object | | `evidence.domain_authentication.dmarc.exists` | boolean | | `evidence.domain_authentication.dmarc.policy` | string | | `evidence.domain_authentication.dmarc.record` | string \| null | | `evidence.domain_authentication.dmarc.percentage` | integer \| null | | `evidence.domain_authentication.mta_sts` | object | | `evidence.domain_authentication.mta_sts.exists` | boolean | | `evidence.domain_authentication.mta_sts.record` | string \| null | | `evidence.domain_authentication.tls_rpt` | object | | `evidence.domain_authentication.tls_rpt.exists` | boolean | | `evidence.domain_authentication.tls_rpt.record` | string \| null | | `evidence.domain_authentication.issues[]` | string[] | | `recommendation` | object | | `recommendation.signup` | string | | `recommendation.marketing` | string | | `recommendation.cold_outreach` | string | | `deliverability` | object | | `deliverability.status` | string | | `deliverability.sub_status` | string | | `deliverability.safe_to_send` | boolean | | `deliverability.mailbox_checked` | boolean | | `deliverability.smtp_confirmed` | boolean | | `deliverability.domain_accepts_mail` | boolean | | `deliverability.accepts_all` | boolean \| null | | `deliverability.is_role` | boolean | | `deliverability.is_free_provider` | boolean | | `deliverability.is_disposable` | boolean | | `deliverability.is_toxic` | boolean | | `deliverability.is_no_reply` | boolean | | `deliverability.is_gibberish` | boolean | | `suggestions` | object | | `suggestions.did_you_mean` | string \| null | | `limitations[]` | string[] | | `tier` | string | | `credits_used` | integer | | `verified_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/email/verify?email=user%40company.com&full=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/email/verify?email=user%40company.com&full=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/email/verify?email=user%40company.com&full=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/email/verify?email=user%40company.com&full=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/verify?email=user%40company.com&full=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "email": "jane.doe@acme-widgets.com", "normalized_email": "jane.doe@acme-widgets.com", "risk": "low", "confidence": 0.62, "confidence_level": "medium", "decision": "accept", "reasons": [ "mx_found", "not_disposable", "redundant_mx_records", "domain_authentication_strong", "mailbox_not_checked" ], "signals": { "syntax": { "status": "pass", "confidence": 1, "reason": "syntax_valid" }, "dns": { "status": "pass", "confidence": 0.92, "reason": "mx_found", "details": { "mx_records": [ "mx1.mailhost-example.net", "mx2.mailhost-example.net" ], "null_mx": false } }, "mailbox": { "status": "not_checked", "confidence": 0.35, "reason": "mailbox_not_checked" }, "catch_all": { "status": "unknown", "confidence": 0.35, "reason": "not_checked" }, "disposable": { "status": "pass", "confidence": 0.7, "reason": "not_disposable", "details": { "confidence": null } }, "role": { "status": "pass", "confidence": 0.86, "reason": "not_role_based", "details": { "role_type": null } }, "free_provider": { "status": "pass", "confidence": 0.9, "reason": "business_or_custom_domain", "details": { "provider": null } }, "reputation": { "status": "pass", "confidence": 0.72, "reason": "not_listed", "details": { "threat_level": "none" } }, "typo": { "status": "pass", "confidence": 0.7, "reason": "no_common_provider_typo", "details": { "did_you_mean": null } }, "random_input": { "status": "pass", "confidence": 0.65, "reason": "not_random_like" }, "reserved_domain": { "status": "pass", "confidence": 0.78, "reason": "not_reserved_domain", "details": { "domain": "acme-widgets.com", "tld": "com", "reserved": false, "domain_literal": false } }, "domain_profile": { "status": "pass", "confidence": 0.68, "reason": "clean_domain_profile", "details": { "normalized": "acme-widgets.com", "tld": "com", "label_count": 2, "reserved": false, "domain_literal": false, "punycode": false, "suspicious_reasons": [] } }, "local_part": { "status": "pass", "confidence": 0.66, "reason": "clean_local_part", "details": { "base_local_part": "jane.doe", "numeric_ratio": 0, "separator_count": 1, "suspicious_reasons": [] } }, "subaddressing": { "status": "pass", "confidence": 0.65, "reason": "no_plus_tag", "details": { "plus_addressed": false, "base_local_part": "jane.doe", "tag": null } }, "mx_redundancy": { "status": "pass", "confidence": 0.82, "reason": "redundant_mx_records", "details": { "mx_count": 2 } }, "domain_authentication": { "status": "pass", "confidence": 0.86, "reason": "domain_authentication_strong", "details": { "checked": true, "spf": { "exists": true, "policy": "fail", "record": "v=spf1 include:_spf.mailhost-example.net -all" }, "dmarc": { "exists": true, "policy": "reject", "record": "v=DMARC1; p=reject; rua=mailto:dmarc@acme-widgets.com", "percentage": null }, "mta_sts": { "exists": true, "record": "v=STSv1; id=20260101T000000" }, "tls_rpt": { "exists": true, "record": "v=TLSRPTv1; rua=mailto:tls@acme-widgets.com" }, "status": "strong", "issues": [] } }, "toxicity": { "status": "pass", "confidence": 0.68, "reason": "not_toxic", "details": { "score": 0, "toxic": false, "do_not_mail": false, "reasons": [] } }, "provider_profile": { "status": "unknown", "confidence": 0.55, "reason": "custom_domain_mail", "details": { "provider": null, "category": "custom_domain_mail", "confidence": 0.55 } }, "smtp_server": { "status": "not_checked", "confidence": 0, "reason": "not_checked" } }, "evidence": { "mx_records": [ "mx1.mailhost-example.net", "mx2.mailhost-example.net" ], "provider": null, "checked_via": [ "worker" ], "normalized_parts": { "local_part": "jane.doe", "domain": "acme-widgets.com", "base_local_part": "jane.doe", "tag": null }, "domain_profile": { "tld": "com", "label_count": 2, "reserved": false, "domain_literal": false, "punycode": false, "suspicious_reasons": [] }, "domain_authentication": { "checked": true, "spf": { "exists": true, "policy": "fail", "record": "v=spf1 include:_spf.mailhost-example.net -all" }, "dmarc": { "exists": true, "policy": "reject", "record": "v=DMARC1; p=reject; rua=mailto:dmarc@acme-widgets.com", "percentage": null }, "mta_sts": { "exists": true, "record": "v=STSv1; id=20260101T000000" }, "tls_rpt": { "exists": true, "record": "v=TLSRPTv1; rua=mailto:tls@acme-widgets.com" }, "status": "strong", "issues": [] } }, "recommendation": { "signup": "allow", "marketing": "send", "cold_outreach": "send" }, "deliverability": { "status": "deliverable", "sub_status": "mx_verified", "safe_to_send": true, "mailbox_checked": false, "smtp_confirmed": false, "domain_accepts_mail": true, "accepts_all": null, "is_role": false, "is_free_provider": false, "is_disposable": false, "is_toxic": false, "is_no_reply": false, "is_gibberish": false }, "suggestions": { "did_you_mean": null }, "limitations": [ "basic_tier_does_not_confirm_mailbox_existence" ], "result": "valid", "result_detail": "mx_verified", "verification": { "syntax_valid": true, "mx_found": true, "mx_records": [ "mx1.mailhost-example.net", "mx2.mailhost-example.net" ], "null_mx": false, "smtp_verified": null, "mailbox_exists": null, "catch_all": null, "full_inbox": null, "smtp_provider": null }, "classification": { "disposable": false, "disposable_confidence": null, "role_based": false, "role_type": null, "free_provider": false, "provider": null }, "reputation": { "dnsbl_listed": false, "threat_level": "none" }, "quality": { "score": 100, "grade": "A", "flags": [] }, "tier": "basic", "credits_used": 2, "verified_at": "2026-10-09T10:15:30.000Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/email/verify/bulk` Operation: `verifyEmailBulk` Credits and authentication: 2 Authentication required POST /v1/email/verify/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | emails | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `summary` | object | | `summary.total` | integer | | `summary.valid` | integer | | `summary.invalid` | integer | | `summary.risky` | integer | | `summary.unknown` | integer | | `summary.pending` | integer | | `credits_used` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/email/verify/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "emails": [ "jane.doe@example.com", "support@example.org" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/email/verify/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "emails": [ "jane.doe@example.com", "support@example.org" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/email/verify/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "emails": [ "jane.doe@example.com", "support@example.org", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "emails": [ "jane.doe@example.com", "support@example.org" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/email/verify/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/email/verify/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "emails" => [ "jane.doe@example.com", "support@example.org" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ {} ], "summary": { "total": 3, "valid": 2, "invalid": 0, "risky": 1, "unknown": 0, "pending": 0 }, "credits_used": 6 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/phone-validation # Phone Number Intelligence API Parse, validate, classify, and format global phone numbers, then add offline location, time zone, original prefix carrier, dialing, short-code, and regulator allocation context when available. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/phone-number-validation-api) ## Operations POST `/v1/phone/validate` [View API reference](https://domscan.net/docs/products/phone-validation#validatePhoneNumber) POST `/v1/phone/validate/bulk` [View API reference](https://domscan.net/docs/products/phone-validation#validatePhoneNumbersBulk) ## POST `/v1/phone/validate` Operation: `validatePhoneNumber` Credits and authentication: 1 Authentication required POST /v1/phone/validate Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | phone | string | required | | default_country | string | optional | | expected_country | string | optional | | dialing_from_country | string | optional | | language | string | optional | #### Response fields | Field | Type | | --- | --- | | `input` | string | | `normalized_input` | string | | `kind` | string | | `valid` | boolean | | `possible` | boolean | | `status` | string | | `recommendation` | string | | `validation_level` | string | | `reason` | string \| null | | `warnings[]` | string[] | | `number` | object | | `number.e164` | string | | `number.international` | string | | `number.national` | string | | `number.rfc3966` | string | | `number.national_number` | string | | `number.extension` | string \| null | | `number.country` | string \| null | | `number.country_name` | string \| null | | `number.country_calling_code` | string | | `number.possible_countries[]` | string[] | | `number.country_match` | boolean \| null | | `number.type` | string | | `number.non_geographic` | boolean | | `live_checks` | object | | `live_checks.assignment` | string | | `live_checks.reachability` | string | | `live_checks.current_carrier` | string | | `live_checks.subscriber_identity` | string | | `live_checks.porting` | string | | `privacy` | object | | `privacy.upstream_requests` | integer | | `privacy.telecom_provider_queried` | boolean | | `privacy.persisted` | boolean | | `privacy.domscan_edge_relay_used` | boolean | | `privacy.third_party_requests` | integer | | `intelligence` | object | | `intelligence.status` | string | | `intelligence.kind` | string \| null | | `intelligence.reason` | string \| null | | `intelligence.coverage` | object | | `intelligence.coverage.country` | string \| null | | `intelligence.coverage.level` | string | | `intelligence.coverage.global_numbering_metadata` | boolean | | `intelligence.coverage.official_snapshot_available` | boolean | | `intelligence.coverage.official_allocation_match` | boolean | | `intelligence.coverage.official_source_ids[]` | string[] | | `intelligence.coverage.matching_source_ids[]` | string[] | | `intelligence.coverage.current_carrier_lookup` | boolean | | `intelligence.location` | object | | `intelligence.location.label` | string \| null | | `intelligence.location.country_name` | string \| null | | `intelligence.location.country` | string \| null | | `intelligence.location.language` | string | | `intelligence.location.granularity` | string | | `intelligence.location.current_physical_location` | boolean | | `intelligence.possible_time_zones` | object | | `intelligence.possible_time_zones.values[]` | string[] | | `intelligence.possible_time_zones.current_location` | boolean | | `intelligence.possible_time_zones.inference` | string | | `intelligence.original_prefix_carrier` | object | | `intelligence.original_prefix_carrier.name` | string \| null | | `intelligence.original_prefix_carrier.source_id` | string \| null | | `intelligence.original_prefix_carrier.evidence` | string | | `intelligence.original_prefix_carrier.current_carrier` | boolean | | `intelligence.original_prefix_carrier.portability_may_change_carrier` | boolean | | `intelligence.portability` | object | | `intelligence.portability.region_supported` | boolean | | `intelligence.portability.current_port_checked` | boolean | | `intelligence.dialing` | object | | `intelligence.dialing.from_country` | string \| null | | `intelligence.dialing.international` | string \| null | | `intelligence.dialing.mobile` | string \| null | | `intelligence.dialing.internationally_diallable` | boolean | | `intelligence.number_details` | object | | `intelligence.number_details.geographical` | boolean | | `intelligence.number_details.geographical_area_code` | string \| null | | `intelligence.number_details.geographical_area_code_length` | integer | | `intelligence.number_details.national_destination_code` | string \| null | | `intelligence.number_details.national_destination_code_length` | integer | | `intelligence.number_details.subscriber_number_length` | integer | | `intelligence.number_details.mobile_token` | string \| null | | `intelligence.service_signals` | object | | `intelligence.service_signals.number_type` | string | | `intelligence.service_signals.geographical` | boolean | | `intelligence.service_signals.toll_free` | boolean | | `intelligence.service_signals.premium_rate` | boolean | | `intelligence.service_signals.shared_cost` | boolean | | `intelligence.service_signals.voip` | boolean | | `intelligence.service_signals.personal_number` | boolean | | `intelligence.service_signals.likely_sms_capable` | boolean \| null | | `intelligence.short_number` | object | | `intelligence.short_number.region` | string | | `intelligence.short_number.possible` | boolean | | `intelligence.short_number.valid` | boolean | | `intelligence.short_number.emergency` | boolean | | `intelligence.short_number.connects_to_emergency` | boolean | | `intelligence.short_number.sms_service` | boolean | | `intelligence.short_number.carrier_specific` | boolean | | `intelligence.short_number.expected_cost` | string | | `intelligence.regulator_allocations[]` | object[] | | `intelligence.regulator_allocations[]` | object | | `intelligence.regulator_allocations[].authority` | string | | `intelligence.regulator_allocations[].country` | string | | `intelligence.regulator_allocations[].matched_prefix` | string | | `intelligence.regulator_allocations[].matched_range_end` | string \| null | | `intelligence.regulator_allocations[].match_kind` | string | | `intelligence.regulator_allocations[].category` | string | | `intelligence.regulator_allocations[].status` | string | | `intelligence.regulator_allocations[].original_assignee` | string \| null | | `intelligence.regulator_allocations[].operator_code` | string \| null | | `intelligence.regulator_allocations[].region` | string \| null | | `intelligence.regulator_allocations[].service_description` | string \| null | | `intelligence.regulator_allocations[].assigned_on` | string \| null | | `intelligence.regulator_allocations[].effective_on` | string \| null | | `intelligence.regulator_allocations[].expires_on` | string \| null | | `intelligence.regulator_allocations[].current_operator` | boolean | | `intelligence.regulator_allocations[].portability_included` | boolean | | `intelligence.regulator_allocations[].individual_number_assignment_checked` | boolean | | `intelligence.regulator_allocations[].source_id` | string | | `intelligence.regulator_allocations[].source_file` | string \| null | | `intelligence.regulator_allocations[].details` | object | | `intelligence.sources[]` | object[] | | `intelligence.sources[]` | object | | `intelligence.sources[].id` | string | | `intelligence.sources[].name` | string | | `intelligence.sources[].type` | string | | `intelligence.sources[].version` | string \| null | | `intelligence.sources[].updated_at` | string \| null | | `intelligence.sources[].retrieved_at` | string \| null | | `intelligence.sources[].age_days` | integer \| null | | `intelligence.sources[].record_count` | integer \| null | | `intelligence.sources[].license` | string \| null | | `intelligence.sources[].license_url` | string \| null | | `intelligence.sources[].url` | string | | `intelligence.sources[].attribution` | string \| null | | `intelligence.warnings[]` | string[] | | `intelligence.relay` | object | | `intelligence.relay.configured` | boolean | | `intelligence.relay.used` | boolean | | `intelligence.relay.persisted` | boolean | | `limitations[]` | string[] | | `metadata` | object | | `metadata.engine` | string | | `metadata.metadata_basis` | string | | `credits_used` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/phone/validate" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "phone": "+34 612 345 678", "default_country": "ES", "expected_country": "ES", "dialing_from_country": "ES", "language": "es" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/phone/validate", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "phone": "+34 612 345 678", "default_country": "ES", "expected_country": "ES", "dialing_from_country": "ES", "language": "es" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/phone/validate", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "phone": "+34 612 345 678", "default_country": "ES", "expected_country": "ES", "dialing_from_country": "ES", "language": "es", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "phone": "+34 612 345 678", "default_country": "ES", "expected_country": "ES", "dialing_from_country": "ES", "language": "es" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/phone/validate", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/phone/validate") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "phone" => "+34 612 345 678", "default_country" => "ES", "expected_country" => "ES", "dialing_from_country" => "ES", "language" => "es" }) #### Example response ```json { "input": "+44 20 7946 0123", "normalized_input": "+44 20 7946 0123", "validation_level": "numbering_plan", "live_checks": { "assignment": "not_checked", "reachability": "not_checked", "current_carrier": "not_checked", "subscriber_identity": "not_checked", "porting": "not_checked" }, "privacy": { "upstream_requests": 0, "telecom_provider_queried": false, "persisted": false, "domscan_edge_relay_used": true, "third_party_requests": 0 }, "intelligence": { "status": "available", "kind": "phone_number", "reason": null, "coverage": { "country": "GB", "level": "global_numbering_metadata", "global_numbering_metadata": true, "official_snapshot_available": false, "official_allocation_match": false, "official_source_ids": [], "matching_source_ids": [], "current_carrier_lookup": false }, "location": { "label": "London", "country_name": "United Kingdom", "country": "GB", "language": "en", "granularity": "numbering_plan_area", "current_physical_location": false }, "possible_time_zones": { "values": [ "Europe/London" ], "current_location": false, "inference": "number_prefix" }, "original_prefix_carrier": { "name": null, "source_id": null, "evidence": "unavailable", "current_carrier": false, "portability_may_change_carrier": true }, "portability": { "region_supported": true, "current_port_checked": false }, "dialing": { "from_country": "US", "international": "011 44 20 7946 0123", "mobile": "+44 20 7946 0123", "internationally_diallable": true }, "number_details": { "geographical": true, "geographical_area_code": "20", "geographical_area_code_length": 2, "national_destination_code": "20", "national_destination_code_length": 2, "subscriber_number_length": 8, "mobile_token": null }, "service_signals": { "number_type": "fixed_line", "geographical": true, "toll_free": false, "premium_rate": false, "shared_cost": false, "voip": false, "personal_number": false, "likely_sms_capable": null }, "short_number": null, "regulator_allocations": [], "sources": [ { "id": "google_libphonenumber", "name": "Google libphonenumber metadata", "type": "offline_metadata", "version": "9.0.34", "license": "Apache-2.0", "url": "https://github.com/google/libphonenumber" } ], "warnings": [ "LOCATION_IS_NUMBERING_PLAN_AREA_NOT_DEVICE_LOCATION", "CARRIER_IS_ORIGINAL_PREFIX_CARRIER_NOT_CURRENT_CARRIER", "ALLOCATION_DOES_NOT_PROVE_INDIVIDUAL_ASSIGNMENT", "NO_CURRENT_PORTABILITY_LOOKUP", "NO_LIVE_TELECOM_CHECKS" ], "relay": { "configured": true, "used": true, "persisted": false } }, "limitations": [ "NUMBERING_PLAN_ONLY", "DOES_NOT_PROVE_ASSIGNMENT", "NO_LIVE_TELECOM_CHECKS" ], "metadata": { "engine": "libphonenumber-js/max", "metadata_basis": "Google libphonenumber numbering plans" }, "kind": "phone_number", "valid": true, "possible": true, "status": "valid", "recommendation": "accept", "reason": null, "warnings": [], "number": { "e164": "+442079460123", "international": "+44 20 7946 0123", "national": "020 7946 0123", "rfc3966": "tel:+442079460123", "national_number": "2079460123", "extension": null, "country": "GB", "country_name": "United Kingdom", "country_calling_code": "44", "possible_countries": [ "GB" ], "country_match": true, "type": "fixed_line", "non_geographic": false }, "credits_used": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests - `500` Server Error ## POST `/v1/phone/validate/bulk` Operation: `validatePhoneNumbersBulk` Credits and authentication: 1 Authentication required POST /v1/phone/validate/bulk Credits: 1/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | phones | unknown[] | required | | default_country | string | optional | | expected_country | string | optional | | dialing_from_country | string | optional | | language | string | optional | #### Response fields | Field | Type | | --- | --- | | `total` | integer | | `valid_count` | integer | | `possible_only_count` | integer | | `invalid_count` | integer | | `validation_level` | string | | `results[]` | object[] | | `results[]` | object | | `results[].input` | string | | `results[].normalized_input` | string | | `results[].kind` | string | | `results[].valid` | boolean | | `results[].possible` | boolean | | `results[].status` | string | | `results[].recommendation` | string | | `results[].validation_level` | string | | `results[].reason` | string \| null | | `results[].warnings[]` | string[] | | `results[].number` | object | | `results[].number.e164` | string | | `results[].number.international` | string | | `results[].number.national` | string | | `results[].number.rfc3966` | string | | `results[].number.national_number` | string | | `results[].number.extension` | string \| null | | `results[].number.country` | string \| null | | `results[].number.country_name` | string \| null | | `results[].number.country_calling_code` | string | | `results[].number.possible_countries[]` | string[] | | `results[].number.country_match` | boolean \| null | | `results[].number.type` | string | | `results[].number.non_geographic` | boolean | | `results[].live_checks` | object | | `results[].live_checks.assignment` | string | | `results[].live_checks.reachability` | string | | `results[].live_checks.current_carrier` | string | | `results[].live_checks.subscriber_identity` | string | | `results[].live_checks.porting` | string | | `results[].privacy` | object | | `results[].privacy.upstream_requests` | integer | | `results[].privacy.telecom_provider_queried` | boolean | | `results[].privacy.persisted` | boolean | | `results[].privacy.domscan_edge_relay_used` | boolean | | `results[].privacy.third_party_requests` | integer | | `results[].intelligence` | object | | `results[].intelligence.status` | string | | `results[].intelligence.kind` | string \| null | | `results[].intelligence.reason` | string \| null | | `results[].intelligence.coverage` | object | | `results[].intelligence.coverage.country` | string \| null | | `results[].intelligence.coverage.level` | string | | `results[].intelligence.coverage.global_numbering_metadata` | boolean | | `results[].intelligence.coverage.official_snapshot_available` | boolean | | `results[].intelligence.coverage.official_allocation_match` | boolean | | `results[].intelligence.coverage.official_source_ids[]` | string[] | | `results[].intelligence.coverage.matching_source_ids[]` | string[] | | `results[].intelligence.coverage.current_carrier_lookup` | boolean | | `results[].intelligence.location` | object | | `results[].intelligence.location.label` | string \| null | | `results[].intelligence.location.country_name` | string \| null | | `results[].intelligence.location.country` | string \| null | | `results[].intelligence.location.language` | string | | `results[].intelligence.location.granularity` | string | | `results[].intelligence.location.current_physical_location` | boolean | | `results[].intelligence.possible_time_zones` | object | | `results[].intelligence.possible_time_zones.values[]` | string[] | | `results[].intelligence.possible_time_zones.current_location` | boolean | | `results[].intelligence.possible_time_zones.inference` | string | | `results[].intelligence.original_prefix_carrier` | object | | `results[].intelligence.original_prefix_carrier.name` | string \| null | | `results[].intelligence.original_prefix_carrier.source_id` | string \| null | | `results[].intelligence.original_prefix_carrier.evidence` | string | | `results[].intelligence.original_prefix_carrier.current_carrier` | boolean | | `results[].intelligence.original_prefix_carrier.portability_may_change_carrier` | boolean | | `results[].intelligence.portability` | object | | `results[].intelligence.portability.region_supported` | boolean | | `results[].intelligence.portability.current_port_checked` | boolean | | `results[].intelligence.dialing` | object | | `results[].intelligence.dialing.from_country` | string \| null | | `results[].intelligence.dialing.international` | string \| null | | `results[].intelligence.dialing.mobile` | string \| null | | `results[].intelligence.dialing.internationally_diallable` | boolean | | `results[].intelligence.number_details` | object | | `results[].intelligence.number_details.geographical` | boolean | | `results[].intelligence.number_details.geographical_area_code` | string \| null | | `results[].intelligence.number_details.geographical_area_code_length` | integer | | `results[].intelligence.number_details.national_destination_code` | string \| null | | `results[].intelligence.number_details.national_destination_code_length` | integer | | `results[].intelligence.number_details.subscriber_number_length` | integer | | `results[].intelligence.number_details.mobile_token` | string \| null | | `results[].intelligence.service_signals` | object | | `results[].intelligence.service_signals.number_type` | string | | `results[].intelligence.service_signals.geographical` | boolean | | `results[].intelligence.service_signals.toll_free` | boolean | | `results[].intelligence.service_signals.premium_rate` | boolean | | `results[].intelligence.service_signals.shared_cost` | boolean | | `results[].intelligence.service_signals.voip` | boolean | | `results[].intelligence.service_signals.personal_number` | boolean | | `results[].intelligence.service_signals.likely_sms_capable` | boolean \| null | | `results[].intelligence.short_number` | object | | `results[].intelligence.short_number.region` | string | | `results[].intelligence.short_number.possible` | boolean | | `results[].intelligence.short_number.valid` | boolean | | `results[].intelligence.short_number.emergency` | boolean | | `results[].intelligence.short_number.connects_to_emergency` | boolean | | `results[].intelligence.short_number.sms_service` | boolean | | `results[].intelligence.short_number.carrier_specific` | boolean | | `results[].intelligence.short_number.expected_cost` | string | | `results[].intelligence.regulator_allocations[]` | object[] | | `results[].intelligence.regulator_allocations[]` | object | | `results[].intelligence.regulator_allocations[].authority` | string | | `results[].intelligence.regulator_allocations[].country` | string | | `results[].intelligence.regulator_allocations[].matched_prefix` | string | | `results[].intelligence.regulator_allocations[].matched_range_end` | string \| null | | `results[].intelligence.regulator_allocations[].match_kind` | string | | `results[].intelligence.regulator_allocations[].category` | string | | `results[].intelligence.regulator_allocations[].status` | string | | `results[].intelligence.regulator_allocations[].original_assignee` | string \| null | | `results[].intelligence.regulator_allocations[].operator_code` | string \| null | | `results[].intelligence.regulator_allocations[].region` | string \| null | | `results[].intelligence.regulator_allocations[].service_description` | string \| null | | `results[].intelligence.regulator_allocations[].assigned_on` | string \| null | | `results[].intelligence.regulator_allocations[].effective_on` | string \| null | | `results[].intelligence.regulator_allocations[].expires_on` | string \| null | | `results[].intelligence.regulator_allocations[].current_operator` | boolean | | `results[].intelligence.regulator_allocations[].portability_included` | boolean | | `results[].intelligence.regulator_allocations[].individual_number_assignment_checked` | boolean | | `results[].intelligence.regulator_allocations[].source_id` | string | | `results[].intelligence.regulator_allocations[].source_file` | string \| null | | `results[].intelligence.regulator_allocations[].details` | object | | `results[].intelligence.sources[]` | object[] | | `results[].intelligence.sources[]` | object | | `results[].intelligence.sources[].id` | string | | `results[].intelligence.sources[].name` | string | | `results[].intelligence.sources[].type` | string | | `results[].intelligence.sources[].version` | string \| null | | `results[].intelligence.sources[].updated_at` | string \| null | | `results[].intelligence.sources[].retrieved_at` | string \| null | | `results[].intelligence.sources[].age_days` | integer \| null | | `results[].intelligence.sources[].record_count` | integer \| null | | `results[].intelligence.sources[].license` | string \| null | | `results[].intelligence.sources[].license_url` | string \| null | | `results[].intelligence.sources[].url` | string | | `results[].intelligence.sources[].attribution` | string \| null | | `results[].intelligence.warnings[]` | string[] | | `results[].intelligence.relay` | object | | `results[].intelligence.relay.configured` | boolean | | `results[].intelligence.relay.used` | boolean | | `results[].intelligence.relay.persisted` | boolean | | `results[].limitations[]` | string[] | | `results[].metadata` | object | | `results[].metadata.engine` | string | | `results[].metadata.metadata_basis` | string | | `credits_used` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/phone/validate/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "expected_country": "ES", "dialing_from_country": "US", "language": "en", "phones": [ "+34 612 345 678", { "phone": "0491 570 006", "default_country": "AU", "expected_country": "AU", "dialing_from_country": "GB", "language": "en" }, "+800 1234 5678" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/phone/validate/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "expected_country": "ES", "dialing_from_country": "US", "language": "en", "phones": [ "+34 612 345 678", { "phone": "0491 570 006", "default_country": "AU", "expected_country": "AU", "dialing_from_country": "GB", "language": "en" }, "+800 1234 5678" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/phone/validate/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "expected_country": "ES", "dialing_from_country": "US", "language": "en", "phones": [ "+34 612 345 678", { "phone": "0491 570 006", "default_country": "AU", "expected_country": "AU", "dialing_from_country": "GB", "language": "en", }, "+800 1234 5678", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "expected_country": "ES", "dialing_from_country": "US", "language": "en", "phones": [ "+34 612 345 678", { "phone": "0491 570 006", "default_country": "AU", "expected_country": "AU", "dialing_from_country": "GB", "language": "en" }, "+800 1234 5678" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/phone/validate/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/phone/validate/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "expected_country" => "ES", "dialing_from_country" => "US", "language" => "en", "phones" => [ "+34 612 345 678", { "phone" => "0491 570 006", "default_country" => "AU", "expected_country" => "AU", "dialing_from_country" => "GB", "language" => "en" }, "+800 1234 5678" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "total": 1, "valid_count": 1, "possible_only_count": 1, "invalid_count": 1, "validation_level": "numbering_plan", "results": [ { "input": "example", "normalized_input": "example", "kind": "phone_number", "valid": true, "possible": false, "status": "valid", "recommendation": "accept", "validation_level": "numbering_plan", "reason": "DEFAULT_COUNTRY_REQUIRED", "warnings": [ "COUNTRY_MISMATCH" ], "number": { "e164": "+34612345678", "international": "+34 612 34 56 78", "national": "612 34 56 78", "rfc3966": "tel:+34612345678", "national_number": "612345678", "extension": null, "country": "ES", "country_name": "Spain", "country_calling_code": "34", "possible_countries": [ "ES" ], "country_match": false, "type": "fixed_line", "non_geographic": false }, "live_checks": { "assignment": "not_checked", "reachability": "not_checked", "current_carrier": "not_checked", "subscriber_identity": "not_checked", "porting": "not_checked" }, "privacy": { "upstream_requests": 0, "telecom_provider_queried": false, "persisted": false, "domscan_edge_relay_used": false, "third_party_requests": 0 }, "intelligence": { "status": "available", "kind": "phone_number", "reason": "example", "coverage": { "country": "US", "level": "global_numbering_metadata", "global_numbering_metadata": false, "official_snapshot_available": true, "official_allocation_match": false, "official_source_ids": [ "example" ], "matching_source_ids": [ "example" ], "current_carrier_lookup": false }, "location": { "label": "Madrid", "country_name": "Spain", "country": "ES", "language": "es", "granularity": "numbering_plan_area", "current_physical_location": false }, "possible_time_zones": { "values": [ "Europe/Madrid" ], "current_location": false, "inference": "number_prefix" }, "original_prefix_carrier": { "name": "Vodafone", "source_id": "nanpa_us", "evidence": "offline_prefix_metadata", "current_carrier": false, "portability_may_change_carrier": false }, "portability": { "region_supported": false, "current_port_checked": false }, "dialing": { "from_country": "US", "international": "011 34 612 34 56 78", "mobile": "+34 612 34 56 78", "internationally_diallable": false }, "number_details": { "geographical": false, "geographical_area_code": "example", "geographical_area_code_length": 1, "national_destination_code": "example", "national_destination_code_length": 1, "subscriber_number_length": 1, "mobile_token": "example" }, "service_signals": { "number_type": "fixed_line", "geographical": false, "toll_free": false, "premium_rate": false, "shared_cost": false, "voip": false, "personal_number": false, "likely_sms_capable": false }, "short_number": { "region": "ES", "possible": false, "valid": true, "emergency": false, "connects_to_emergency": false, "sms_service": false, "carrier_specific": false, "expected_cost": "toll_free" }, "regulator_allocations": [ { "authority": "CNMC", "country": "ES", "matched_prefix": "912", "matched_range_end": "example", "match_kind": "prefix", "category": "geographic", "status": "assigned", "original_assignee": "Example Telecom", "operator_code": "example", "region": "Madrid", "service_description": "example", "assigned_on": "2026-08-27", "effective_on": "2026-08-27", "expires_on": "2026-08-27", "current_operator": false, "portability_included": false, "individual_number_assignment_checked": false, "source_id": "cnmc", "source_file": "example", "details": {} } ], "sources": [ { "id": "google_libphonenumber", "name": "Google libphonenumber metadata", "type": "offline_metadata", "url": "https://example.com", "version": "9.0.34", "updated_at": "2026-08-27T12:00:00Z", "retrieved_at": "2026-08-27T12:00:00Z", "age_days": 1, "record_count": 1, "license": "Apache-2.0", "license_url": "https://example.com", "attribution": "example" } ], "warnings": [ "example" ], "relay": { "configured": false, "used": false, "persisted": false } }, "limitations": [ "example" ], "metadata": { "engine": "libphonenumber-js/max", "metadata_basis": "Google libphonenumber numbering plans" } } ], "credits_used": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests - `500` Server Error ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/company-lookup # Company Lookup API Look up company information associated with a domain. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/company-lookup-api) ## Operations GET `/v1/company` [View API reference](https://domscan.net/docs/products/company-lookup#getCompany) ## GET `/v1/company` Operation: `getCompany` Credits and authentication: 3 Authentication required GET /v1/company Credits: 3 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `domain` | string | | `company` | object | | `company.name` | string \| null | | `company.legal_name` | string \| null | | `company.description` | string \| null | | `company.founded_year` | integer \| null | | `company.industry` | string \| null | | `company.employee_count_range` | string \| null | | `company.type` | string \| null | | `location` | object | | `social` | object | | `social.linkedin` | string \| null | | `social.twitter` | string \| null | | `social.facebook` | string \| null | | `social.github` | string \| null | | `tech` | object | | `tech.email_provider` | string \| null | | `tech.website_technologies[]` | string[] | | `confidence` | number | | `evidence_summary` | object | | `evidence_summary.sources[]` | string[] | | `evidence_summary.source_count` | integer | | `evidence_summary.confidence` | number | | `evidence_summary.confidence_label` | string | | `evidence_summary.company_field_count` | integer | | `evidence_summary.social_profile_count` | integer | | `evidence_summary.email_provider_detected` | boolean | | `evidence_summary.website_technology_count` | integer | | `evidence_summary.cache_status` | string | | `meta` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/company?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/company?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/company?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/company?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/company?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "domain": "example.com", "company": { "name": "Example Co", "legal_name": null, "description": "Example Co builds simple tools for small teams.", "founded_year": null, "industry": null, "employee_count_range": null, "type": null }, "location": { "headquarters": null }, "social": { "linkedin": "https://www.linkedin.com/company/example-co", "twitter": null, "facebook": null, "github": "https://github.com/example-co" }, "tech": { "email_provider": "Google Workspace", "website_technologies": [] }, "confidence": 0.8, "evidence_summary": { "sources": [ "meta_tags", "dns", "social_links" ], "source_count": 3, "confidence": 0.8, "confidence_label": "high", "company_field_count": 2, "social_profile_count": 2, "email_provider_detected": true, "website_technology_count": 0, "cache_status": "miss" }, "meta": { "sources": [ "meta_tags", "dns", "social_links" ], "query_time_ms": 1320, "cached": false } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/identity-assets # Website Identity Assets API Extract source-backed logos, favicons, preview assets, theme colors, and declared profiles from public websites. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/company-logo-api) ## Operations GET `/v1/identity-assets` [View API reference](https://domscan.net/docs/products/identity-assets#getWebsiteIdentityAssets) POST `/v1/identity-assets/bulk` [View API reference](https://domscan.net/docs/products/identity-assets#bulkGetWebsiteIdentityAssets) ## GET `/v1/identity-assets` Operation: `getWebsiteIdentityAssets` Credits and authentication: 2 Authentication required GET /v1/identity-assets Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | skip_cache | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `domain` | string | | `website_url` | string | | `fetch_state` | string | | `organization_name` | string \| null | | `assets` | object | | `assets.logo_url` | string \| null | | `assets.logo_kind` | string \| null | | `assets.logo_source` | string \| null | | `assets.logo_verification` | string \| null | | `assets.favicon_url` | string \| null | | `assets.touch_icon_url` | string \| null | | `assets.preview_image_url` | string \| null | | `assets.manifest_url` | string \| null | | `assets.theme_color` | string \| null | | `assets.candidates[]` | object[] | | `assets.candidates[]` | object | | `assets.candidates[].url` | string | | `assets.candidates[].kind` | string | | `assets.candidates[].source` | string | | `assets.candidates[].type` | string \| null | | `assets.candidates[].sizes` | string \| null | | `assets.candidates[].score` | integer | | `assets.candidates[].confidence` | string | | `social_profiles[]` | object[] | | `social_profiles[]` | object | | `social_profiles[].platform` | string | | `social_profiles[].type` | string | | `social_profiles[].handle` | string \| null | | `social_profiles[].url` | string | | `social_profiles[].source` | string | | `social_profiles[].confidence` | string | | `confidence` | number | | `evidence[]` | string[] | | `meta` | object | | `meta.checked_at` | string | | `meta.cached` | boolean | | `meta.fetch_transport` | string | | `meta.fetch_error` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/identity-assets?domain=example.com&skip_cache=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/identity-assets?domain=example.com&skip_cache=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/identity-assets?domain=example.com&skip_cache=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/identity-assets?domain=example.com&skip_cache=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/identity-assets?domain=example.com&skip_cache=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "domain": "www.example.com", "website_url": "https://www.example.com/", "fetch_state": "ok", "organization_name": "Example Co", "assets": { "logo_url": "https://www.example.com/logo.png", "logo_kind": "logo", "logo_source": "json_ld:logo", "logo_verification": "verified", "favicon_url": "https://www.example.com/favicon.ico", "touch_icon_url": "https://www.example.com/apple-touch-icon.png", "preview_image_url": "https://www.example.com/og.png", "manifest_url": "https://www.example.com/site.webmanifest", "theme_color": "#0b5fff", "candidates": [ { "url": "https://www.example.com/logo.png", "kind": "logo", "source": "json_ld:logo", "type": null, "sizes": null, "score": 100, "confidence": "high" }, { "url": "https://www.example.com/apple-touch-icon.png", "kind": "touch_icon", "source": "link:apple-touch-icon", "type": null, "sizes": "180x180", "score": 80, "confidence": "high" }, { "url": "https://www.example.com/favicon.ico", "kind": "favicon", "source": "link:icon", "type": null, "sizes": "48x48", "score": 60, "confidence": "medium" }, { "url": "https://www.example.com/og.png", "kind": "preview_image", "source": "open_graph:image", "type": null, "sizes": null, "score": 30, "confidence": "low" } ] }, "social_profiles": [ { "platform": "linkedin", "type": "social", "handle": "example-co", "url": "https://www.linkedin.com/company/example-co", "source": "same_as", "confidence": "high" }, { "platform": "github", "type": "developer", "handle": "example-co", "url": "https://github.com/example-co", "source": "same_as", "confidence": "high" } ], "confidence": 1, "evidence": [ "organization_name", "structured_logo", "asset_verified", "declared_icon", "declared_social_profiles" ], "meta": { "checked_at": "2026-10-09T10:15:30.000Z", "cached": false, "fetch_transport": "edge_relay" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## POST `/v1/identity-assets/bulk` Operation: `bulkGetWebsiteIdentityAssets` Credits and authentication: 2 Authentication required POST /v1/identity-assets/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `results[].input` | string | | `results[].data` | object | | `results[].error` | object | | `results[].error.error` | object | | `results[].error.error.code` | string | | `results[].error.error.type` | string | | `results[].error.error.message` | string | | `results[].error.error.status` | integer | | `results[].error.error.retryable` | boolean | | `results[].error.error.request_id` | string | | `results[].error.error.suggestion` | string | | `results[].error.error.details` | object | | `results[].error.error.retry_after` | integer | | `results[].error.error.docs_url` | string | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.unknown` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/identity-assets/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "stripe.com", "github.com" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/identity-assets/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "stripe.com", "github.com" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/identity-assets/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "stripe.com", "github.com", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "stripe.com", "github.com" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/identity-assets/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/identity-assets/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "stripe.com", "github.com" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "input": "example", "data": {}, "error": { "error": { "code": "INVALID_DOMAIN", "type": "authentication_error", "message": "Invalid domain format", "status": 400, "retryable": false, "request_id": "request-id", "docs_url": "https://domscan.net/docs/check-availability", "suggestion": "example", "details": {}, "retry_after": 300 } } } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "unknown": 1, "max_items": 10, "credits_per_item": 2, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/identity-resolution # Internet Identity Resolution API Resolve a company domain into public identities explicitly declared by its website. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/domain-to-social-profiles-api) ## Operations GET `/v1/identity-resolution` [View API reference](https://domscan.net/docs/products/identity-resolution#resolveInternetIdentity) POST `/v1/identity-resolution/bulk` [View API reference](https://domscan.net/docs/products/identity-resolution#bulkResolveInternetIdentity) ## GET `/v1/identity-resolution` Operation: `resolveInternetIdentity` Credits and authentication: 2 Authentication required GET /v1/identity-resolution Credits: 2 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | skip_cache | string Allowed values `1` | optional | #### Response fields | Field | Type | | --- | --- | | `cache_age_s` | integer | | `query` | string | | `canonical_domain` | string | | `website_url` | string | | `fetch_state` | string | | `organization` | object | | `organization.name` | string \| null | | `organization.description` | string \| null | | `identities[]` | object[] | | `identities[]` | object | | `identities[].platform` | string | | `identities[].type` | string | | `identities[].handle` | string \| null | | `identities[].url` | string | | `identities[].source` | string | | `identities[].confidence` | string | | `contacts` | object | | `contacts.emails[]` | string[] | | `contacts.phones[]` | string[] | | `confidence` | number | | `evidence` | object | | `evidence.declared_identity_count` | integer | | `evidence.high_confidence_count` | integer | | `evidence.medium_confidence_count` | integer | | `evidence.sources[]` | string[] | | `meta` | object | | `meta.checked_at` | string | | `meta.cached` | boolean | | `meta.fetch_transport` | string | | `meta.fetch_error` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/identity-resolution?domain=example.com&skip_cache=1" ``` ```javascript const response = await fetch("https://domscan.net/v1/identity-resolution?domain=example.com&skip_cache=1", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/identity-resolution?domain=example.com&skip_cache=1", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/identity-resolution?domain=example.com&skip_cache=1", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/identity-resolution?domain=example.com&skip_cache=1") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "query": "example", "canonical_domain": "example.com", "website_url": "https://example.com", "fetch_state": "ok", "organization": { "name": "example", "description": "example" }, "identities": [ { "platform": "github", "type": "social", "url": "https://example.com", "source": "same_as", "confidence": "high", "handle": "example" } ], "contacts": { "emails": [ "user@example.com", "admin@example.org" ], "phones": [ "example" ] }, "confidence": 0.85, "evidence": { "declared_identity_count": 1, "high_confidence_count": 1, "medium_confidence_count": 1, "sources": [ "example" ] }, "meta": { "checked_at": "2026-08-27T12:00:00Z", "cached": false, "fetch_transport": "worker", "fetch_error": "timeout" }, "cache_age_s": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests - `502` Bad Gateway ## POST `/v1/identity-resolution/bulk` Operation: `bulkResolveInternetIdentity` Credits and authentication: 2 Authentication required POST /v1/identity-resolution/bulk Credits: 2/item #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | #### Response fields | Field | Type | | --- | --- | | `results[]` | object[] | | `results[]` | object | | `results[].input` | string | | `results[].data` | object | | `results[].error` | object | | `results[].error.error` | object | | `results[].error.error.code` | string | | `results[].error.error.type` | string | | `results[].error.error.message` | string | | `results[].error.error.status` | integer | | `results[].error.error.retryable` | boolean | | `results[].error.error.request_id` | string | | `results[].error.error.suggestion` | string | | `results[].error.error.details` | object | | `results[].error.error.retry_after` | integer | | `results[].error.error.docs_url` | string | | `meta` | object | | `meta.total` | integer | | `meta.succeeded` | integer | | `meta.failed` | integer | | `meta.unknown` | integer | | `meta.max_items` | integer | | `meta.credits_per_item` | integer | | `meta.duration_ms` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/identity-resolution/bulk" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "stripe.com", "github.com" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/identity-resolution/bulk", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "stripe.com", "github.com" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/identity-resolution/bulk", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "stripe.com", "github.com", ], }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "stripe.com", "github.com" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/identity-resolution/bulk", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/identity-resolution/bulk") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "stripe.com", "github.com" ] }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "results": [ { "input": "example", "data": {}, "error": { "error": { "code": "INVALID_DOMAIN", "type": "authentication_error", "message": "Invalid domain format", "status": 400, "retryable": false, "request_id": "request-id", "docs_url": "https://domscan.net/docs/check-availability", "suggestion": "example", "details": {}, "retry_after": 300 } } } ], "meta": { "total": 1, "succeeded": 1, "failed": 1, "unknown": 1, "max_items": 10, "credits_per_item": 2, "duration_ms": 1 } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/watchlist # Domain Watchlist API Manage your domain watchlist. Get notified when domains become available or change status. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/watchlist-api) ## Operations GET `/v1/watchlist` [View API reference](https://domscan.net/docs/products/watchlist#getWatchlist) POST `/v1/watchlist` [View API reference](https://domscan.net/docs/products/watchlist#addToWatchlist) DELETE `/v1/watchlist` [View API reference](https://domscan.net/docs/products/watchlist#removeFromWatchlist) GET `/v1/watchlist/expiring` [View API reference](https://domscan.net/docs/products/watchlist#getExpiringWatchlist) GET `/v1/watchlist/available` [View API reference](https://domscan.net/docs/products/watchlist#getAvailableWatchlist) GET `/v1/webhooks` [View API reference](https://domscan.net/docs/products/watchlist#listAlertWebhooks)[Read the guide](https://domscan.net/webhook-alerts-api) POST `/v1/webhooks` [View API reference](https://domscan.net/docs/products/watchlist#createAlertWebhook)[Read the guide](https://domscan.net/webhook-alerts-api) PATCH `/v1/webhooks/:webhook_id` [View API reference](https://domscan.net/docs/products/watchlist#updateAlertWebhook)[Read the guide](https://domscan.net/webhook-alerts-api) DELETE `/v1/webhooks/:webhook_id` [View API reference](https://domscan.net/docs/products/watchlist#deleteAlertWebhook)[Read the guide](https://domscan.net/webhook-alerts-api) POST `/v1/webhooks/:webhook_id/test` [View API reference](https://domscan.net/docs/products/watchlist#testAlertWebhook)[Read the guide](https://domscan.net/webhook-alerts-api) POST `/v1/webhooks/:webhook_id/rotate-secret` [View API reference](https://domscan.net/docs/products/watchlist#rotateAlertWebhookSecret)[Read the guide](https://domscan.net/webhook-alerts-api) GET `/v1/webhooks/:webhook_id/deliveries` [View API reference](https://domscan.net/docs/products/watchlist#listAlertWebhookDeliveries)[Read the guide](https://domscan.net/webhook-alerts-api) GET `/v1/watchlist/alerts` [View API reference](https://domscan.net/docs/products/watchlist#listWatchlistAlerts)[Read the guide](https://domscan.net/webhook-alerts-api) POST `/v1/watchlist/alerts` [View API reference](https://domscan.net/docs/products/watchlist#createWatchlistAlert)[Read the guide](https://domscan.net/webhook-alerts-api) GET `/v1/watchlist/alerts/:subscription_id` [View API reference](https://domscan.net/docs/products/watchlist#getWatchlistAlert)[Read the guide](https://domscan.net/webhook-alerts-api) PATCH `/v1/watchlist/alerts/:subscription_id` [View API reference](https://domscan.net/docs/products/watchlist#updateWatchlistAlert)[Read the guide](https://domscan.net/webhook-alerts-api) DELETE `/v1/watchlist/alerts/:subscription_id` [View API reference](https://domscan.net/docs/products/watchlist#deleteWatchlistAlert)[Read the guide](https://domscan.net/webhook-alerts-api) ## GET `/v1/watchlist` Operation: `getWatchlist` Credits and authentication: 1 Authentication required GET /v1/watchlist Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `watchlist[]` | object[] | | `watchlist[]` | object | | `watchlist[].domain` | string | | `watchlist[].added_at` | string | | `watchlist[].status` | string | | `watchlist[].last_checked` | string | | `watchlist[].expiry_date` | string | | `watchlist[].days_until_expiry` | integer | | `watchlist[].notify_email` | string | | `watchlist[].check_count` | integer | | `total` | integer | | `updated_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/watchlist" ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/watchlist", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/watchlist", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "watchlist": [ { "domain": "example.com", "added_at": "2024-01-01T00:00:00Z", "status": "registered", "last_checked": "2024-01-15T12:00:00Z" } ], "total": 1, "updated_at": "2024-01-15T12:00:00Z" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/watchlist` Operation: `addToWatchlist` Credits and authentication: 1 Authentication required POST /v1/watchlist Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | notify_email | string | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `message` | string | | `watchlist[]` | object[] | | `watchlist[]` | object | | `watchlist[].domain` | string | | `watchlist[].added_at` | string | | `watchlist[].status` | string | | `watchlist[].last_checked` | string | | `watchlist[].expiry_date` | string | | `watchlist[].days_until_expiry` | integer | | `watchlist[].notify_email` | string | | `watchlist[].check_count` | integer | | `total` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/watchlist" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domain": "example.org", "notify_email": "alerts@example.com" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domain": "example.org", "notify_email": "alerts@example.com" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/watchlist", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domain": "example.org", "notify_email": "alerts@example.com", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "domain": "example.org", "notify_email": "alerts@example.com" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/watchlist", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domain" => "example.org", "notify_email" => "alerts@example.com" }) #### Example response ```json { "success": true, "message": "Added example.org to watchlist", "watchlist": [ { "domain": "example.com", "added_at": "2026-06-02T09:12:00.000Z", "last_checked": "2026-10-09T03:00:12.000Z", "status": "expiring_soon", "expiry_date": "2026-12-18T14:22:08Z", "days_until_expiry": 70, "notify_email": "alerts@example.com" }, { "domain": "example.org", "added_at": "2026-10-09T10:15:30.000Z", "status": "unknown", "notify_email": "alerts@example.com" } ], "total": 2 } ``` #### HTTP status codes - `201` Created - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## DELETE `/v1/watchlist` Operation: `removeFromWatchlist` Credits and authentication: Free Authentication required DELETE /v1/watchlist Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `message` | string | | `domain` | string | | `watchlist[]` | object[] | | `watchlist[]` | object | | `watchlist[].domain` | string | | `watchlist[].added_at` | string | | `watchlist[].status` | string | | `watchlist[].last_checked` | string | | `watchlist[].expiry_date` | string | | `watchlist[].days_until_expiry` | integer | | `watchlist[].notify_email` | string | | `watchlist[].check_count` | integer | | `total` | integer | #### Example request ```bash curl -X DELETE "https://domscan.net/v1/watchlist?domain=example.com" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist?domain=example.com", { method: "DELETE", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.delete( "https://domscan.net/v1/watchlist?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodDelete, "https://domscan.net/v1/watchlist?domain=example.com", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist?domain=example.com") request = Net::HTTP::Delete.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "success": true, "message": "Request completed", "domain": "example.com", "watchlist": [ { "domain": "example.com", "added_at": "2026-08-27T12:00:00Z", "status": "registered", "last_checked": "2026-08-27T12:00:00Z", "expiry_date": "2026-08-27T12:00:00Z", "days_until_expiry": 1, "notify_email": "user@example.com", "check_count": 1 } ], "total": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/watchlist/expiring` Operation: `getExpiringWatchlist` Credits and authentication: 1 Authentication required GET /v1/watchlist/expiring Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | days | integer Default `90` | optional | | limit | integer | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `expiring_domains[]` | object[] | | `expiring_domains[]` | object | | `expiring_domains[].domain` | string | | `expiring_domains[].added_at` | string | | `expiring_domains[].status` | string | | `expiring_domains[].last_checked` | string | | `expiring_domains[].expiry_date` | string | | `expiring_domains[].days_until_expiry` | integer | | `expiring_domains[].notify_email` | string | | `expiring_domains[].check_count` | integer | | `total` | integer | | `threshold_days` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/watchlist/expiring?days=90" ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/expiring?days=90", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/watchlist/expiring?days=90", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/watchlist/expiring?days=90", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/expiring?days=90") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "expiring_domains": [ { "domain": "example.com", "added_at": "2026-06-02T09:12:00.000Z", "last_checked": "2026-10-09T03:00:12.000Z", "status": "expiring_soon", "expiry_date": "2026-12-18T14:22:08Z", "days_until_expiry": 70, "notify_email": "alerts@example.com" } ], "total": 1, "threshold_days": 90 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/watchlist/available` Operation: `getAvailableWatchlist` Credits and authentication: 1 Authentication required GET /v1/watchlist/available Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `available_domains[]` | object[] | | `available_domains[]` | object | | `available_domains[].domain` | string | | `available_domains[].added_at` | string | | `available_domains[].status` | string | | `available_domains[].last_checked` | string | | `available_domains[].expiry_date` | string | | `available_domains[].days_until_expiry` | integer | | `available_domains[].notify_email` | string | | `available_domains[].check_count` | integer | | `total` | integer | | `message` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/watchlist/available" ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/available", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/watchlist/available", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/watchlist/available", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/available") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "has_more": false, "next_cursor": "example", "available_domains": [ { "domain": "example.com", "added_at": "2026-08-27T12:00:00Z", "status": "registered", "last_checked": "2026-08-27T12:00:00Z", "expiry_date": "2026-08-27T12:00:00Z", "days_until_expiry": 1, "notify_email": "user@example.com", "check_count": 1 } ], "total": 1, "message": "Request completed" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/webhooks` Operation: `listAlertWebhooks` Credits and authentication: Free Authentication required GET /v1/webhooks Credits: 0 #### Response fields | Field | Type | | --- | --- | | `endpoints[]` | object[] | | `endpoints[]` | object | | `endpoints[].id` | string | | `endpoints[].url` | string | | `endpoints[].description` | string \| null | | `endpoints[].events[]` | string[] | | `endpoints[].status` | string | | `endpoints[].disabled_reason` | string \| null | | `endpoints[].consecutive_failures` | integer | | `endpoints[].secret_hint` | string | | `endpoints[].previous_secret_expires_at` | string \| null | | `endpoints[].secret_rotated_at` | string \| null | | `endpoints[].last_success_at` | string \| null | | `endpoints[].last_failure_at` | string \| null | | `endpoints[].last_error` | string \| null | | `endpoints[].created_at` | string | | `endpoints[].updated_at` | string | | `endpoints[].disabled_at` | string \| null | | `available_events[]` | string[] | | `all_events` | string | | `test_event` | string | | `policy` | object | | `policy.secret_rotation_grace_seconds` | integer | | `policy.secret_rotation_credits` | integer | | `policy.credits_per_delivered_alert` | integer | | `policy.test_event_credits` | integer | | `policy.job_event_credits` | integer | | `policy.failed_deliveries_charged` | boolean | | `policy.max_endpoints` | integer | | `policy.max_attempts` | integer | | `policy.disable_after_consecutive_failures` | integer | | `policy.signature_tolerance_seconds` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/webhooks" ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/webhooks", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/webhooks", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "endpoints": [ { "id": "example-id", "url": "https://example.com", "events": [ "example" ], "status": "active", "secret_hint": "example", "created_at": "2026-08-27T12:00:00Z", "description": "example", "disabled_reason": "customer", "consecutive_failures": 1, "previous_secret_expires_at": "2026-08-27T12:00:00Z", "secret_rotated_at": "2026-08-27T12:00:00Z", "last_success_at": "2026-08-27T12:00:00Z", "last_failure_at": "2026-08-27T12:00:00Z", "last_error": "example", "updated_at": "2026-08-27T12:00:00Z", "disabled_at": "2026-08-27T12:00:00Z" } ], "available_events": [ "domain.available" ], "policy": { "credits_per_delivered_alert": 2, "test_event_credits": 0, "failed_deliveries_charged": false, "max_endpoints": 1, "max_attempts": 1, "disable_after_consecutive_failures": 1, "signature_tolerance_seconds": 1, "secret_rotation_grace_seconds": 86400, "secret_rotation_credits": 0, "job_event_credits": 0 }, "all_events": "*", "test_event": "webhook.test" } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## POST `/v1/webhooks` Operation: `createAlertWebhook` Credits and authentication: Free Authentication required POST /v1/webhooks Credits: 0 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | url | string | required | | description | string \| null | optional | | events | unknown[] | optional | #### Response fields | Field | Type | | --- | --- | | `endpoint` | object | | `endpoint.id` | string | | `endpoint.url` | string | | `endpoint.description` | string \| null | | `endpoint.events[]` | string[] | | `endpoint.status` | string | | `endpoint.disabled_reason` | string \| null | | `endpoint.consecutive_failures` | integer | | `endpoint.secret_hint` | string | | `endpoint.previous_secret_expires_at` | string \| null | | `endpoint.secret_rotated_at` | string \| null | | `endpoint.last_success_at` | string \| null | | `endpoint.last_failure_at` | string \| null | | `endpoint.last_error` | string \| null | | `endpoint.created_at` | string | | `endpoint.updated_at` | string | | `endpoint.disabled_at` | string \| null | | `secret` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/webhooks" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "url": "https://hooks.example.com/domscan", "description": "Production alerts", "events": [ "domain.expiring_30", "domain.available", "domain.dns_changed" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "url": "https://hooks.example.com/domscan", "description": "Production alerts", "events": [ "domain.expiring_30", "domain.available", "domain.dns_changed" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/webhooks", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "url": "https://hooks.example.com/domscan", "description": "Production alerts", "events": [ "domain.expiring_30", "domain.available", "domain.dns_changed", ], }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "url": "https://hooks.example.com/domscan", "description": "Production alerts", "events": [ "domain.expiring_30", "domain.available", "domain.dns_changed" ] }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/webhooks", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "url" => "https://hooks.example.com/domscan", "description" => "Production alerts", "events" => [ "domain.expiring_30", "domain.available", "domain.dns_changed" ] }) #### Example response ```json { "endpoint": { "id": "example-id", "url": "https://example.com", "events": [ "example" ], "status": "active", "secret_hint": "example", "created_at": "2026-08-27T12:00:00Z", "description": "example", "disabled_reason": "customer", "consecutive_failures": 1, "previous_secret_expires_at": "2026-08-27T12:00:00Z", "secret_rotated_at": "2026-08-27T12:00:00Z", "last_success_at": "2026-08-27T12:00:00Z", "last_failure_at": "2026-08-27T12:00:00Z", "last_error": "example", "updated_at": "2026-08-27T12:00:00Z", "disabled_at": "2026-08-27T12:00:00Z" }, "secret": "example" } ``` #### HTTP status codes - `201` Created - `400` Bad Request - `401` Unauthorized - `409` HTTP 409 - `429` Too Many Requests ## PATCH `/v1/webhooks/:webhook_id` Operation: `updateAlertWebhook` Credits and authentication: Free Authentication required PATCH /v1/webhooks/:webhook_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | webhook_id | string | required | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | enabled | boolean | optional | | description | string \| null | optional | | events | unknown[] | optional | #### Response fields | Field | Type | | --- | --- | | `endpoint` | object | | `endpoint.id` | string | | `endpoint.url` | string | | `endpoint.description` | string \| null | | `endpoint.events[]` | string[] | | `endpoint.status` | string | | `endpoint.disabled_reason` | string \| null | | `endpoint.consecutive_failures` | integer | | `endpoint.secret_hint` | string | | `endpoint.previous_secret_expires_at` | string \| null | | `endpoint.secret_rotated_at` | string \| null | | `endpoint.last_success_at` | string \| null | | `endpoint.last_failure_at` | string \| null | | `endpoint.last_error` | string \| null | | `endpoint.created_at` | string | | `endpoint.updated_at` | string | | `endpoint.disabled_at` | string \| null | #### Example request ```bash curl -X PATCH "https://domscan.net/v1/webhooks/string" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "enabled": true, "events": [ "*" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks/string", { method: "PATCH", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "enabled": true, "events": [ "*" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.patch( "https://domscan.net/v1/webhooks/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "enabled": True, "events": [ "*", ], }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "enabled": true, "events": [ "*" ] }`) req, err := http.NewRequest(http.MethodPatch, "https://domscan.net/v1/webhooks/string", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks/string") request = Net::HTTP::Patch.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "enabled" => true, "events" => [ "*" ] }) #### Example response ```json { "endpoint": { "id": "example-id", "url": "https://example.com", "events": [ "example" ], "status": "active", "secret_hint": "example", "created_at": "2026-08-27T12:00:00Z", "description": "example", "disabled_reason": "customer", "consecutive_failures": 1, "previous_secret_expires_at": "2026-08-27T12:00:00Z", "secret_rotated_at": "2026-08-27T12:00:00Z", "last_success_at": "2026-08-27T12:00:00Z", "last_failure_at": "2026-08-27T12:00:00Z", "last_error": "example", "updated_at": "2026-08-27T12:00:00Z", "disabled_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## DELETE `/v1/webhooks/:webhook_id` Operation: `deleteAlertWebhook` Credits and authentication: Free Authentication required DELETE /v1/webhooks/:webhook_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | webhook_id | string | required | #### Response fields | Field | Type | | --- | --- | | `id` | string | | `deleted` | boolean | #### Example request ```bash curl -X DELETE "https://domscan.net/v1/webhooks/string" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks/string", { method: "DELETE", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.delete( "https://domscan.net/v1/webhooks/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodDelete, "https://domscan.net/v1/webhooks/string", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks/string") request = Net::HTTP::Delete.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "id": "example-id", "deleted": true } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## POST `/v1/webhooks/:webhook_id/test` Operation: `testAlertWebhook` Credits and authentication: Free Authentication required POST /v1/webhooks/:webhook_id/test Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | webhook_id | string | required | #### Response fields | Field | Type | | --- | --- | | `delivery` | object | | `delivery.id` | string | | `delivery.endpoint_id` | string | | `delivery.event_id` | string | | `delivery.event_type` | string | | `delivery.status` | string | | `delivery.attempts` | integer | | `delivery.next_attempt_at` | string \| null | | `delivery.last_attempt_at` | string \| null | | `delivery.response_status` | integer \| null | | `delivery.last_error` | string \| null | | `delivery.credits_charged` | integer | | `delivery.refunded` | boolean | | `delivery.created_at` | string | | `delivery.delivered_at` | string \| null | | `delivered` | boolean | #### Example request ```bash curl -X POST "https://domscan.net/v1/webhooks/string/test" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks/string/test", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/webhooks/string/test", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/webhooks/string/test", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks/string/test") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "delivery": { "id": "example-id", "endpoint_id": "example", "event_id": "example", "event_type": "domain", "status": "pending", "attempts": 1, "next_attempt_at": "2026-08-27T12:00:00Z", "last_attempt_at": "2026-08-27T12:00:00Z", "response_status": 1, "last_error": "example", "credits_charged": 1, "refunded": false, "created_at": "2026-08-27T12:00:00Z", "delivered_at": "2026-08-27T12:00:00Z" }, "delivered": false } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `409` HTTP 409 - `429` Too Many Requests ## POST `/v1/webhooks/:webhook_id/rotate-secret` Operation: `rotateAlertWebhookSecret` Credits and authentication: Free Authentication required POST /v1/webhooks/:webhook_id/rotate-secret Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | webhook_id | string | required | #### Response fields | Field | Type | | --- | --- | | `endpoint` | object | | `endpoint.id` | string | | `endpoint.url` | string | | `endpoint.description` | string \| null | | `endpoint.events[]` | string[] | | `endpoint.status` | string | | `endpoint.disabled_reason` | string \| null | | `endpoint.consecutive_failures` | integer | | `endpoint.secret_hint` | string | | `endpoint.previous_secret_expires_at` | string \| null | | `endpoint.secret_rotated_at` | string \| null | | `endpoint.last_success_at` | string \| null | | `endpoint.last_failure_at` | string \| null | | `endpoint.last_error` | string \| null | | `endpoint.created_at` | string | | `endpoint.updated_at` | string | | `endpoint.disabled_at` | string \| null | | `secret` | string | | `previous_secret_expires_at` | string | | `grace_period_seconds` | integer | #### Example request ```bash curl -X POST "https://domscan.net/v1/webhooks/string/rotate-secret" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks/string/rotate-secret", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/webhooks/string/rotate-secret", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/webhooks/string/rotate-secret", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks/string/rotate-secret") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "endpoint": { "id": "whe_3f1c0a9b8e7d6c5b4a39281706f5e4d3", "url": "https://hooks.example.com/domscan", "events": [ "*" ], "status": "active", "secret_hint": "4b7a", "previous_secret_expires_at": "2026-10-11T12:00:00.000Z", "secret_rotated_at": "2026-10-10T12:00:00.000Z", "created_at": "2026-10-01T09:30:00.000Z" }, "secret": "whsec_...", "previous_secret_expires_at": "2026-10-11T12:00:00.000Z", "grace_period_seconds": 86400 } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/webhooks/:webhook_id/deliveries` Operation: `listAlertWebhookDeliveries` Credits and authentication: Free Authentication required GET /v1/webhooks/:webhook_id/deliveries Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | webhook_id | string | required | | limit | integer Default `50` | optional | #### Response fields | Field | Type | | --- | --- | | `endpoint_id` | string | | `deliveries[]` | object[] | | `deliveries[]` | object | | `deliveries[].id` | string | | `deliveries[].endpoint_id` | string | | `deliveries[].event_id` | string | | `deliveries[].event_type` | string | | `deliveries[].status` | string | | `deliveries[].attempts` | integer | | `deliveries[].next_attempt_at` | string \| null | | `deliveries[].last_attempt_at` | string \| null | | `deliveries[].response_status` | integer \| null | | `deliveries[].last_error` | string \| null | | `deliveries[].credits_charged` | integer | | `deliveries[].refunded` | boolean | | `deliveries[].created_at` | string | | `deliveries[].delivered_at` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/webhooks/string/deliveries?limit=25" ``` ```javascript const response = await fetch("https://domscan.net/v1/webhooks/string/deliveries?limit=25", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/webhooks/string/deliveries?limit=25", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/webhooks/string/deliveries?limit=25", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/webhooks/string/deliveries?limit=25") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "endpoint_id": "example", "deliveries": [ { "id": "example-id", "endpoint_id": "example", "event_id": "example", "event_type": "domain", "status": "pending", "attempts": 1, "next_attempt_at": "2026-08-27T12:00:00Z", "last_attempt_at": "2026-08-27T12:00:00Z", "response_status": 1, "last_error": "example", "credits_charged": 1, "refunded": false, "created_at": "2026-08-27T12:00:00Z", "delivered_at": "2026-08-27T12:00:00Z" } ] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/watchlist/alerts` Operation: `listWatchlistAlerts` Credits and authentication: Free Authentication required GET /v1/watchlist/alerts Credits: 0 #### Response fields | Field | Type | | --- | --- | | `subscriptions[]` | object[] | | `subscriptions[]` | object | | `subscriptions[].id` | string | | `subscriptions[].type` | string | | `subscriptions[].target` | string | | `subscriptions[].registrar` | string \| null | | `subscriptions[].events[]` | string[] | | `subscriptions[].status` | string | | `subscriptions[].ssl_expiring_days` | integer \| null | | `subscriptions[].price_type` | string \| null | | `subscriptions[].drop_percent` | number \| null | | `subscriptions[].target_price` | number \| null | | `subscriptions[].currency` | string \| null | | `subscriptions[].record_types[]` | string[] | | `subscriptions[].observed` | object \| null | | `subscriptions[].last_check_at` | string \| null | | `subscriptions[].last_check_status` | string \| null | | `subscriptions[].last_error` | string \| null | | `subscriptions[].next_check_at` | string \| null | | `subscriptions[].created_at` | string | | `subscriptions[].updated_at` | string | | `total` | integer | | `available_types` | object | | `available_types.ssl[]` | string[] | | `available_types.price[]` | string[] | | `available_types.dns[]` | string[] | | `available_types.typosquat[]` | string[] | | `policy` | object | | `policy.credits_per_delivered_alert` | integer | | `policy.check_credits` | integer | | `policy.unknown_checks_charged` | boolean | | `policy.max_subscriptions` | integer | | `policy.max_typosquat_subscriptions` | integer | | `policy.ssl_expiring_days[]` | integer[] | | `policy.default_ssl_expiring_days` | integer | | `policy.record_types[]` | string[] | | `policy.price_types[]` | string[] | | `policy.check_interval_minutes` | object | | `policy.confirmation_checks` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/watchlist/alerts" ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/alerts", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/watchlist/alerts", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/watchlist/alerts", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/alerts") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "subscriptions": [ { "id": "example-id", "type": "ssl", "target": "example", "registrar": "example", "events": [ "ssl.expiring" ], "status": "active", "ssl_expiring_days": 30, "price_type": "registration", "drop_percent": 0.5, "target_price": 0.5, "currency": "USD", "record_types": [ "A" ], "observed": {}, "last_check_at": "2026-08-27T12:00:00Z", "last_check_status": "baseline", "last_error": "example", "next_check_at": "2026-08-27T12:00:00Z", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z" } ], "total": 1, "available_types": { "ssl": [ "ssl.expiring" ], "price": [ "price.dropped" ], "dns": [ "dns.changed" ], "typosquat": [ "typosquat.detected" ] }, "policy": { "credits_per_delivered_alert": 2, "check_credits": 0, "unknown_checks_charged": false, "max_subscriptions": 1, "check_interval_minutes": {}, "max_typosquat_subscriptions": 1, "ssl_expiring_days": [ 1 ], "default_ssl_expiring_days": 1, "record_types": [ "A" ], "price_types": [ "registration" ], "confirmation_checks": {} } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `429` Too Many Requests ## POST `/v1/watchlist/alerts` Operation: `createWatchlistAlert` Credits and authentication: Free Authentication required POST /v1/watchlist/alerts Credits: 0 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | type | string Allowed values `ssl`, `price`, `dns`, `typosquat` | required | | domain | string | optional | | tld | string | optional | | registrar | string \| null | optional | | events | string[] Allowed values `ssl.expiring`, `ssl.expired`, `ssl.changed`, `price.dropped`, `dns.changed`, `typosquat.detected` | optional | | ssl_expiring_days | integer Allowed values `30`, `14`, `7`, `1` Default `14` | optional | | price_type | string Allowed values `registration`, `renewal` Default `registration` | optional | | drop_percent | number \| null | optional | | target_price | number \| null | optional | | record_types | string[] Allowed values `A`, `AAAA`, `MX`, `NS`, `TXT`, `CNAME` | optional | #### Response fields | Field | Type | | --- | --- | | `subscription` | object | | `subscription.id` | string | | `subscription.type` | string | | `subscription.target` | string | | `subscription.registrar` | string \| null | | `subscription.events[]` | string[] | | `subscription.status` | string | | `subscription.ssl_expiring_days` | integer \| null | | `subscription.price_type` | string \| null | | `subscription.drop_percent` | number \| null | | `subscription.target_price` | number \| null | | `subscription.currency` | string \| null | | `subscription.record_types[]` | string[] | | `subscription.observed` | object \| null | | `subscription.last_check_at` | string \| null | | `subscription.last_check_status` | string \| null | | `subscription.last_error` | string \| null | | `subscription.next_check_at` | string \| null | | `subscription.created_at` | string | | `subscription.updated_at` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/watchlist/alerts" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "type": "ssl", "domain": "shop.example.com", "events": [ "ssl.expiring", "ssl.changed" ], "ssl_expiring_days": 14 }' ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/alerts", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "type": "ssl", "domain": "shop.example.com", "events": [ "ssl.expiring", "ssl.changed" ], "ssl_expiring_days": 14 }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/watchlist/alerts", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "type": "ssl", "domain": "shop.example.com", "events": [ "ssl.expiring", "ssl.changed", ], "ssl_expiring_days": 14, }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "type": "ssl", "domain": "shop.example.com", "events": [ "ssl.expiring", "ssl.changed" ], "ssl_expiring_days": 14 }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/watchlist/alerts", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/alerts") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "type" => "ssl", "domain" => "shop.example.com", "events" => [ "ssl.expiring", "ssl.changed" ], "ssl_expiring_days" => 14 }) #### Example response ```json { "subscription": { "id": "example-id", "type": "ssl", "target": "example", "registrar": "example", "events": [ "ssl.expiring" ], "status": "active", "ssl_expiring_days": 30, "price_type": "registration", "drop_percent": 0.5, "target_price": 0.5, "currency": "USD", "record_types": [ "A" ], "observed": {}, "last_check_at": "2026-08-27T12:00:00Z", "last_check_status": "baseline", "last_error": "example", "next_check_at": "2026-08-27T12:00:00Z", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `201` Created - `400` Bad Request - `401` Unauthorized - `409` HTTP 409 - `429` Too Many Requests ## GET `/v1/watchlist/alerts/:subscription_id` Operation: `getWatchlistAlert` Credits and authentication: Free Authentication required GET /v1/watchlist/alerts/:subscription_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | subscription_id | string | required | #### Response fields | Field | Type | | --- | --- | | `subscription` | object | | `subscription.id` | string | | `subscription.type` | string | | `subscription.target` | string | | `subscription.registrar` | string \| null | | `subscription.events[]` | string[] | | `subscription.status` | string | | `subscription.ssl_expiring_days` | integer \| null | | `subscription.price_type` | string \| null | | `subscription.drop_percent` | number \| null | | `subscription.target_price` | number \| null | | `subscription.currency` | string \| null | | `subscription.record_types[]` | string[] | | `subscription.observed` | object \| null | | `subscription.last_check_at` | string \| null | | `subscription.last_check_status` | string \| null | | `subscription.last_error` | string \| null | | `subscription.next_check_at` | string \| null | | `subscription.created_at` | string | | `subscription.updated_at` | string | | `events[]` | object[] | | `events[]` | object | | `events[].id` | string | | `events[].event_type` | string | | `events[].detected_at` | string | | `events[].published_at` | string \| null | | `events[].data` | object | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/watchlist/alerts/string" ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/alerts/string", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/watchlist/alerts/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/watchlist/alerts/string", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/alerts/string") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "subscription": { "id": "example-id", "type": "ssl", "target": "example", "registrar": "example", "events": [ "ssl.expiring" ], "status": "active", "ssl_expiring_days": 30, "price_type": "registration", "drop_percent": 0.5, "target_price": 0.5, "currency": "USD", "record_types": [ "A" ], "observed": {}, "last_check_at": "2026-08-27T12:00:00Z", "last_check_status": "baseline", "last_error": "example", "next_check_at": "2026-08-27T12:00:00Z", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z" }, "events": [ { "id": "example-id", "event_type": "ssl.expiring", "detected_at": "2026-08-27T12:00:00Z", "published_at": "2026-08-27T12:00:00Z", "data": {} } ] } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## PATCH `/v1/watchlist/alerts/:subscription_id` Operation: `updateWatchlistAlert` Credits and authentication: Free Authentication required PATCH /v1/watchlist/alerts/:subscription_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | subscription_id | string | required | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | enabled | boolean | optional | | events | string[] Allowed values `ssl.expiring`, `ssl.expired`, `ssl.changed`, `price.dropped`, `dns.changed`, `typosquat.detected` | optional | | ssl_expiring_days | integer Allowed values `30`, `14`, `7`, `1` | optional | | drop_percent | number \| null | optional | | target_price | number \| null | optional | | record_types | string[] Allowed values `A`, `AAAA`, `MX`, `NS`, `TXT`, `CNAME` | optional | #### Response fields | Field | Type | | --- | --- | | `subscription` | object | | `subscription.id` | string | | `subscription.type` | string | | `subscription.target` | string | | `subscription.registrar` | string \| null | | `subscription.events[]` | string[] | | `subscription.status` | string | | `subscription.ssl_expiring_days` | integer \| null | | `subscription.price_type` | string \| null | | `subscription.drop_percent` | number \| null | | `subscription.target_price` | number \| null | | `subscription.currency` | string \| null | | `subscription.record_types[]` | string[] | | `subscription.observed` | object \| null | | `subscription.last_check_at` | string \| null | | `subscription.last_check_status` | string \| null | | `subscription.last_error` | string \| null | | `subscription.next_check_at` | string \| null | | `subscription.created_at` | string | | `subscription.updated_at` | string | #### Example request ```bash curl -X PATCH "https://domscan.net/v1/watchlist/alerts/string" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "enabled": true, "events": [ "ssl.expiring", "ssl.expired", "ssl.changed" ] }' ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/alerts/string", { method: "PATCH", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "enabled": true, "events": [ "ssl.expiring", "ssl.expired", "ssl.changed" ] }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.patch( "https://domscan.net/v1/watchlist/alerts/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "enabled": True, "events": [ "ssl.expiring", "ssl.expired", "ssl.changed", ], }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "enabled": true, "events": [ "ssl.expiring", "ssl.expired", "ssl.changed" ] }`) req, err := http.NewRequest(http.MethodPatch, "https://domscan.net/v1/watchlist/alerts/string", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/alerts/string") request = Net::HTTP::Patch.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "enabled" => true, "events" => [ "ssl.expiring", "ssl.expired", "ssl.changed" ] }) #### Example response ```json { "subscription": { "id": "example-id", "type": "ssl", "target": "example", "registrar": "example", "events": [ "ssl.expiring" ], "status": "active", "ssl_expiring_days": 30, "price_type": "registration", "drop_percent": 0.5, "target_price": 0.5, "currency": "USD", "record_types": [ "A" ], "observed": {}, "last_check_at": "2026-08-27T12:00:00Z", "last_check_status": "baseline", "last_error": "example", "next_check_at": "2026-08-27T12:00:00Z", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## DELETE `/v1/watchlist/alerts/:subscription_id` Operation: `deleteWatchlistAlert` Credits and authentication: Free Authentication required DELETE /v1/watchlist/alerts/:subscription_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | subscription_id | string | required | #### Response fields | Field | Type | | --- | --- | | `id` | string | | `deleted` | boolean | #### Example request ```bash curl -X DELETE "https://domscan.net/v1/watchlist/alerts/string" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/watchlist/alerts/string", { method: "DELETE", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.delete( "https://domscan.net/v1/watchlist/alerts/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodDelete, "https://domscan.net/v1/watchlist/alerts/string", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/watchlist/alerts/string") request = Net::HTTP::Delete.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "id": "example-id", "deleted": true } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/brand-monitor # Brand Monitor API Monitor domains for brand infringement and typosquatting threats. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/brand-monitor-api) ## Operations GET `/v1/brand-monitor` [View API reference](https://domscan.net/docs/products/brand-monitor#getBrandMonitors) POST `/v1/brand-monitor` [View API reference](https://domscan.net/docs/products/brand-monitor#createBrandMonitor) DELETE `/v1/brand-monitor` [View API reference](https://domscan.net/docs/products/brand-monitor#deleteBrandMonitor) POST `/v1/brand-monitor/scan` [View API reference](https://domscan.net/docs/products/brand-monitor#triggerBrandScan) GET `/v1/brand-monitor/status` [View API reference](https://domscan.net/docs/products/brand-monitor#getBrandMonitorStatus) POST `/v1/brand-monitor/reset-baseline` [View API reference](https://domscan.net/docs/products/brand-monitor#resetBrandMonitorBaseline) PUT `/v1/brand-monitor/alerts` [View API reference](https://domscan.net/docs/products/brand-monitor#updateBrandMonitorAlerts) ## GET `/v1/brand-monitor` Operation: `getBrandMonitors` Credits and authentication: 1 Authentication required GET /v1/brand-monitor Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `has_more` | boolean | | `next_cursor` | string \| null | | `brands[]` | object[] | | `brands[]` | object | | `brands[].domain` | string | | `brands[].added_at` | string | | `brands[].last_scan_at` | string \| null | | `brands[].scan_count` | integer | | `brands[].registered_typos` | integer | | `brands[].new_threats_since_baseline` | integer | | `brands[].has_alerts` | boolean | | `brands[].scan_status` | string | | `total` | integer | | `updated_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/brand-monitor" ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/brand-monitor", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/brand-monitor", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "brands": [ { "domain": "example.com", "scan_count": 1, "registered_typos": 1, "new_threats_since_baseline": 1, "has_alerts": false, "added_at": "2026-08-27T12:00:00Z", "last_scan_at": "2026-08-27T12:00:00Z", "scan_status": "pending" } ], "total": 1, "updated_at": "2026-08-27T12:00:00Z", "has_more": false, "next_cursor": "example" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/brand-monitor` Operation: `createBrandMonitor` Credits and authentication: 3 Authentication required POST /v1/brand-monitor Credits: 3 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | alert_email | string | optional | | alert_webhook | string | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `message` | string | | `brand` | object | | `brand.domain` | string | | `brand.baseline_threats` | integer | | `brand.scan_status` | string | | `initial_scan` | object \| null | #### Example request ```bash curl -X POST "https://domscan.net/v1/brand-monitor" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domain": "example.com", "alert_email": "security@example.com", "alert_webhook": "https://hooks.example.com/domscan" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domain": "example.com", "alert_email": "security@example.com", "alert_webhook": "https://hooks.example.com/domscan" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/brand-monitor", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domain": "example.com", "alert_email": "security@example.com", "alert_webhook": "https://hooks.example.com/domscan", }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "domain": "example.com", "alert_email": "security@example.com", "alert_webhook": "https://hooks.example.com/domscan" }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/brand-monitor", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domain" => "example.com", "alert_email" => "security@example.com", "alert_webhook" => "https://hooks.example.com/domscan" }) #### Example response ```json { "success": true, "message": "Request completed", "brand": { "domain": "example.com", "baseline_threats": 1, "scan_status": "pending" }, "initial_scan": {} } ``` #### HTTP status codes - `201` Created - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## DELETE `/v1/brand-monitor` Operation: `deleteBrandMonitor` Credits and authentication: 1 Authentication required DELETE /v1/brand-monitor Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `message` | string | #### Example request ```bash curl -X DELETE "https://domscan.net/v1/brand-monitor?domain=example.com" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor?domain=example.com", { method: "DELETE", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.delete( "https://domscan.net/v1/brand-monitor?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodDelete, "https://domscan.net/v1/brand-monitor?domain=example.com", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor?domain=example.com") request = Net::HTTP::Delete.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "success": true, "message": "Request completed" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/brand-monitor/scan` Operation: `triggerBrandScan` Credits and authentication: 6 Authentication required POST /v1/brand-monitor/scan Credits: 6 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `scan` | object \| null | | `alert` | object | | `alert.level` | string | | `alert.message` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/brand-monitor/scan?domain=example.com" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor/scan?domain=example.com", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/brand-monitor/scan?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/brand-monitor/scan?domain=example.com", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor/scan?domain=example.com") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "success": true, "scan": {}, "alert": { "level": "medium", "message": "Request completed" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/brand-monitor/status` Operation: `getBrandMonitorStatus` Credits and authentication: 1 Authentication required GET /v1/brand-monitor/status Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `brand` | object | | `brand.domain` | string | | `brand.name` | string | | `brand.tld` | string | | `brand.added_at` | string | | `brand.last_scan_at` | string \| null | | `brand.scan_count` | integer | | `threats` | object | | `threats.baseline_count` | integer | | `threats.current_count` | integer | | `threats.new_since_baseline` | integer | | `threats.new_threat_domains[]` | string[] | | `threats.all_registered[]` | string[] | | `alerts` | object | | `alerts.email` | string \| null | | `alerts.webhook` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/brand-monitor/status?domain=example.com" ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor/status?domain=example.com", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/brand-monitor/status?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/brand-monitor/status?domain=example.com", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor/status?domain=example.com") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "brand": { "domain": "example.com", "name": "example", "tld": "com", "added_at": "2026-08-27T12:00:00Z", "last_scan_at": "2026-08-27T12:00:00Z", "scan_count": 1 }, "threats": { "baseline_count": 1, "current_count": 1, "new_since_baseline": 1, "new_threat_domains": [ "example.com" ], "all_registered": [ "example" ] }, "alerts": { "email": "user@example.com", "webhook": "example" } } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `404` Not Found - `429` Too Many Requests ## POST `/v1/brand-monitor/reset-baseline` Operation: `resetBrandMonitorBaseline` Credits and authentication: 1 Authentication required POST /v1/brand-monitor/reset-baseline Credits: 1 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `message` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/brand-monitor/reset-baseline?domain=example.com" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor/reset-baseline?domain=example.com", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/brand-monitor/reset-baseline?domain=example.com", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/brand-monitor/reset-baseline?domain=example.com", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor/reset-baseline?domain=example.com") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "success": true, "message": "Request completed" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## PUT `/v1/brand-monitor/alerts` Operation: `updateBrandMonitorAlerts` Credits and authentication: 1 Authentication required PUT /v1/brand-monitor/alerts Credits: 1 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | alert_email | string \| null | optional | | alert_webhook | string \| null | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `message` | string | #### Example request ```bash curl -X PUT "https://domscan.net/v1/brand-monitor/alerts" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domain": "example.com", "alert_email": "brand-team@example.com", "alert_webhook": "https://hooks.example.com/domscan" }' ``` ```javascript const response = await fetch("https://domscan.net/v1/brand-monitor/alerts", { method: "PUT", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domain": "example.com", "alert_email": "brand-team@example.com", "alert_webhook": "https://hooks.example.com/domscan" }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.put( "https://domscan.net/v1/brand-monitor/alerts", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domain": "example.com", "alert_email": "brand-team@example.com", "alert_webhook": "https://hooks.example.com/domscan", }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domain": "example.com", "alert_email": "brand-team@example.com", "alert_webhook": "https://hooks.example.com/domscan" }`) req, err := http.NewRequest(http.MethodPut, "https://domscan.net/v1/brand-monitor/alerts", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/brand-monitor/alerts") request = Net::HTTP::Put.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domain" => "example.com", "alert_email" => "brand-team@example.com", "alert_webhook" => "https://hooks.example.com/domscan" }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "success": true, "message": "Request completed" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/batch-jobs # Asynchronous API batches API Queue many supported API requests and collect their results without keeping a client connection open. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/async-batch-api) ## Operations POST `/v1/batches` [View API reference](https://domscan.net/docs/products/batch-jobs#createApiBatch) GET `/v1/batches` [View API reference](https://domscan.net/docs/products/batch-jobs#listApiBatches) GET `/v1/batches/:job_id` [View API reference](https://domscan.net/docs/products/batch-jobs#getApiBatch) GET `/v1/batches/:job_id/results` [View API reference](https://domscan.net/docs/products/batch-jobs#getApiBatchResults) DELETE `/v1/batches/:job_id` [View API reference](https://domscan.net/docs/products/batch-jobs#cancelApiBatch) GET `/v1/jobs` [View API reference](https://domscan.net/docs/products/batch-jobs#listJobs) GET `/v1/jobs/:job_id` [View API reference](https://domscan.net/docs/products/batch-jobs#getJob) GET `/v1/jobs/:job_id/results` [View API reference](https://domscan.net/docs/products/batch-jobs#getJobResults) POST `/v1/jobs/:job_id/cancel` [View API reference](https://domscan.net/docs/products/batch-jobs#cancelJob) POST `/v1/estimate` [View API reference](https://domscan.net/docs/products/batch-jobs#estimateRequestCost) ## POST `/v1/batches` Operation: `createApiBatch` Credits and authentication: Free Authentication required POST /v1/batches Credits: 0 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | notify_webhook | unknown | optional | | requests | object[] | required | | webhook | object | optional | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.webhook` | object | | `job.webhook.configured` | boolean | | `job.webhook.status` | string | | `job.webhook.attempts` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.results_csv_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/batches" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "requests": [ { "path": "/v1/status", "query": { "domain": "example.com" }, "reference": "customer-42" }, { "path": "/v1/dns", "query": { "domain": "example.org", "type": "MX" } } ], "webhook": { "url": "https://example.com/hooks/domscan", "secret": "replace-with-a-private-secret" } }' ``` ```javascript const response = await fetch("https://domscan.net/v1/batches", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "requests": [ { "path": "/v1/status", "query": { "domain": "example.com" }, "reference": "customer-42" }, { "path": "/v1/dns", "query": { "domain": "example.org", "type": "MX" } } ], "webhook": { "url": "https://example.com/hooks/domscan", "secret": "replace-with-a-private-secret" } }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/batches", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "requests": [ { "path": "/v1/status", "query": { "domain": "example.com", }, "reference": "customer-42", }, { "path": "/v1/dns", "query": { "domain": "example.org", "type": "MX", }, }, ], "webhook": { "url": "https://example.com/hooks/domscan", "secret": "replace-with-a-private-secret", }, }, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{ "requests": [ { "path": "/v1/status", "query": { "domain": "example.com" }, "reference": "customer-42" }, { "path": "/v1/dns", "query": { "domain": "example.org", "type": "MX" } } ], "webhook": { "url": "https://example.com/hooks/domscan", "secret": "replace-with-a-private-secret" } }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/batches", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/batches") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "requests" => [ { "path" => "/v1/status", "query" => { "domain" => "example.com" }, "reference" => "customer-42" }, { "path" => "/v1/dns", "query" => { "domain" => "example.org", "type" => "MX" } } ], "webhook" => { "url" => "https://example.com/hooks/domscan", "secret" => "replace-with-a-private-secret" } }) #### Example response ```json { "job": { "id": "example-id", "status": "queued", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "webhook": { "configured": false, "status": "not_configured", "attempts": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "results_csv_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `200` OK - `202` Accepted - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `429` Too Many Requests ## GET `/v1/batches` Operation: `listApiBatches` Credits and authentication: Free Authentication required GET /v1/batches Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer Default `25` | optional | #### Response fields | Field | Type | | --- | --- | | `jobs[]` | object[] | | `jobs[]` | object | | `jobs[].id` | string | | `jobs[].status` | string | | `jobs[].total` | integer | | `jobs[].counts` | object | | `jobs[].counts.pending` | integer | | `jobs[].counts.processing` | integer | | `jobs[].counts.succeeded` | integer | | `jobs[].counts.failed` | integer | | `jobs[].counts.cancelled` | integer | | `jobs[].billing` | object | | `jobs[].billing.credits_charged` | integer | | `jobs[].billing.credits_refunded` | integer | | `jobs[].billing.credits_net` | integer | | `jobs[].webhook` | object | | `jobs[].webhook.configured` | boolean | | `jobs[].webhook.status` | string | | `jobs[].webhook.attempts` | integer | | `jobs[].status_url` | string | | `jobs[].results_url` | string | | `jobs[].results_csv_url` | string | | `jobs[].poll_after_ms` | integer \| null | | `jobs[].created_at` | string | | `jobs[].started_at` | string \| null | | `jobs[].completed_at` | string \| null | | `jobs[].cancelled_at` | string \| null | | `jobs[].updated_at` | string | | `jobs[].processing_deadline_at` | string | | `jobs[].results_expires_at` | string | | `retention_hours` | integer | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/batches?limit=25" ``` ```javascript const response = await fetch("https://domscan.net/v1/batches?limit=25", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/batches?limit=25", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/batches?limit=25", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/batches?limit=25") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "jobs": [ { "id": "example-id", "status": "queued", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "webhook": { "configured": false, "status": "not_configured", "attempts": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "results_csv_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } ], "retention_hours": 24 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `429` Too Many Requests ## GET `/v1/batches/:job_id` Operation: `getApiBatch` Credits and authentication: Free Authentication required GET /v1/batches/:job_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.webhook` | object | | `job.webhook.configured` | boolean | | `job.webhook.status` | string | | `job.webhook.attempts` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.results_csv_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/batches/string" ``` ```javascript const response = await fetch("https://domscan.net/v1/batches/string", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/batches/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/batches/string", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/batches/string") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "status": "queued", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "webhook": { "configured": false, "status": "not_configured", "attempts": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "results_csv_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/batches/:job_id/results` Operation: `getApiBatchResults` Credits and authentication: Free Authentication required GET /v1/batches/:job_id/results Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | | after | integer Default `-1` | optional | | limit | integer Default `100` | optional | | format | string Allowed values `json`, `csv` Default `json` | optional | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.webhook` | object | | `job.webhook.configured` | boolean | | `job.webhook.status` | string | | `job.webhook.attempts` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.results_csv_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | | `results[]` | object[] | | `results[]` | object | | `results[].position` | integer | | `results[].reference` | string \| null | | `results[].request` | object | | `results[].request.method` | string | | `results[].request.path` | string | | `results[].request.query` | object | | `results[].status` | string | | `results[].attempts` | integer | | `results[].http_status` | integer \| null | | `results[].result` | object \| null | | `results[].error` | object \| null | | `results[].billing` | object | | `results[].started_at` | string \| null | | `results[].completed_at` | string \| null | | `next_after` | integer \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/batches/example/results?after=-1&limit=25&format=json" ``` ```javascript const response = await fetch("https://domscan.net/v1/batches/example/results?after=-1&limit=25&format=json", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/batches/example/results?after=-1&limit=25&format=json", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/batches/example/results?after=-1&limit=25&format=json", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/batches/example/results?after=-1&limit=25&format=json") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "status": "queued", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "webhook": { "configured": false, "status": "not_configured", "attempts": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "results_csv_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" }, "results": [ { "position": 1, "request": { "method": "GET", "path": "example", "query": {} }, "status": "pending", "attempts": 1, "http_status": 1, "result": {}, "error": {}, "billing": {}, "reference": "example", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z" } ], "next_after": 1 } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## DELETE `/v1/batches/:job_id` Operation: `cancelApiBatch` Credits and authentication: Free Authentication required DELETE /v1/batches/:job_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.status` | string | | `job.total` | integer | | `job.counts` | object | | `job.counts.pending` | integer | | `job.counts.processing` | integer | | `job.counts.succeeded` | integer | | `job.counts.failed` | integer | | `job.counts.cancelled` | integer | | `job.billing` | object | | `job.billing.credits_charged` | integer | | `job.billing.credits_refunded` | integer | | `job.billing.credits_net` | integer | | `job.webhook` | object | | `job.webhook.configured` | boolean | | `job.webhook.status` | string | | `job.webhook.attempts` | integer | | `job.status_url` | string | | `job.results_url` | string | | `job.results_csv_url` | string | | `job.poll_after_ms` | integer \| null | | `job.created_at` | string | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.cancelled_at` | string \| null | | `job.updated_at` | string | | `job.processing_deadline_at` | string | | `job.results_expires_at` | string | #### Example request ```bash curl -X DELETE "https://domscan.net/v1/batches/string" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/batches/string", { method: "DELETE", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.delete( "https://domscan.net/v1/batches/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodDelete, "https://domscan.net/v1/batches/string", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/batches/string") request = Net::HTTP::Delete.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "job": { "id": "example-id", "status": "queued", "total": 1, "counts": { "pending": 1, "processing": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "billing": { "credits_charged": 1, "credits_refunded": 1, "credits_net": 1 }, "webhook": { "configured": false, "status": "not_configured", "attempts": 1 }, "status_url": "https://example.com", "results_url": "https://example.com", "results_csv_url": "https://example.com", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "processing_deadline_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "poll_after_ms": 1, "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "cancelled_at": "2026-08-27T12:00:00Z" } } ``` #### HTTP status codes - `202` Accepted - `401` Unauthorized - `404` Not Found - `409` HTTP 409 - `429` Too Many Requests ## GET `/v1/jobs` Operation: `listJobs` Credits and authentication: Free Authentication required GET /v1/jobs Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | limit | integer Default `25` | optional | | cursor | string | optional | | kind | string Allowed values `batch`, `tech_scan`, `scrape`, `domain_discovery` | optional | #### Response fields | Field | Type | | --- | --- | | `jobs[]` | object[] | | `jobs[]` | object | | `jobs[].id` | string | | `jobs[].kind` | string | | `jobs[].status` | string | | `jobs[].native_status` | string | | `jobs[].created_at` | string \| null | | `jobs[].updated_at` | string \| null | | `jobs[].started_at` | string \| null | | `jobs[].completed_at` | string \| null | | `jobs[].results_expires_at` | string \| null | | `jobs[].progress` | object | | `jobs[].progress.total` | integer | | `jobs[].progress.done` | integer | | `jobs[].progress.succeeded` | integer | | `jobs[].progress.failed` | integer | | `jobs[].progress.cancelled` | integer | | `jobs[].credits` | object | | `jobs[].credits.charged` | integer | | `jobs[].credits.refunded` | integer | | `jobs[].notify_webhook` | object | | `jobs[].notify_webhook.endpoint_id` | string \| null | | `jobs[].notify_webhook.status` | string | | `jobs[].notify_webhook.event_type` | string \| null | | `jobs[].notify_webhook.deliveries` | integer | | `jobs[].links` | object | | `jobs[].links.self` | string | | `jobs[].links.results` | string | | `jobs[].links.cancel` | string \| null | | `limit` | integer | | `has_more` | boolean | | `next_cursor` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/jobs?limit=25&cursor=example&kind=batch" ``` ```javascript const response = await fetch("https://domscan.net/v1/jobs?limit=25&cursor=example&kind=batch", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/jobs?limit=25&cursor=example&kind=batch", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/jobs?limit=25&cursor=example&kind=batch", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/jobs?limit=25&cursor=example&kind=batch") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "jobs": [ { "id": "example-id", "kind": "batch", "status": "queued", "native_status": "queued", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "progress": { "total": 1, "done": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "credits": { "charged": 1, "refunded": 1 }, "notify_webhook": { "endpoint_id": "example", "status": "waiting", "event_type": "job.completed", "deliveries": 1 }, "links": { "self": "https://example.com", "results": "https://example.com", "cancel": "https://example.com" } } ], "limit": 1, "has_more": false, "next_cursor": "example" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `429` Too Many Requests ## GET `/v1/jobs/:job_id` Operation: `getJob` Credits and authentication: Free Authentication required GET /v1/jobs/:job_id Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.kind` | string | | `job.status` | string | | `job.native_status` | string | | `job.created_at` | string \| null | | `job.updated_at` | string \| null | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.results_expires_at` | string \| null | | `job.progress` | object | | `job.progress.total` | integer | | `job.progress.done` | integer | | `job.progress.succeeded` | integer | | `job.progress.failed` | integer | | `job.progress.cancelled` | integer | | `job.credits` | object | | `job.credits.charged` | integer | | `job.credits.refunded` | integer | | `job.notify_webhook` | object | | `job.notify_webhook.endpoint_id` | string \| null | | `job.notify_webhook.status` | string | | `job.notify_webhook.event_type` | string \| null | | `job.notify_webhook.deliveries` | integer | | `job.links` | object | | `job.links.self` | string | | `job.links.results` | string | | `job.links.cancel` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/jobs/string" ``` ```javascript const response = await fetch("https://domscan.net/v1/jobs/string", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/jobs/string", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/jobs/string", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/jobs/string") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "kind": "batch", "status": "queued", "native_status": "queued", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "progress": { "total": 1, "done": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "credits": { "charged": 1, "refunded": 1 }, "notify_webhook": { "endpoint_id": "example", "status": "waiting", "event_type": "job.completed", "deliveries": 1 }, "links": { "self": "https://example.com", "results": "https://example.com", "cancel": "https://example.com" } } } ``` #### HTTP status codes - `200` OK - `401` Unauthorized - `404` Not Found - `429` Too Many Requests ## GET `/v1/jobs/:job_id/results` Operation: `getJobResults` Credits and authentication: Free Authentication required GET /v1/jobs/:job_id/results Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | | limit | integer Default `25` | optional | | cursor | string | optional | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.kind` | string | | `job.status` | string | | `job.native_status` | string | | `job.created_at` | string \| null | | `job.updated_at` | string \| null | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.results_expires_at` | string \| null | | `job.progress` | object | | `job.progress.total` | integer | | `job.progress.done` | integer | | `job.progress.succeeded` | integer | | `job.progress.failed` | integer | | `job.progress.cancelled` | integer | | `job.credits` | object | | `job.credits.charged` | integer | | `job.credits.refunded` | integer | | `job.notify_webhook` | object | | `job.notify_webhook.endpoint_id` | string \| null | | `job.notify_webhook.status` | string | | `job.notify_webhook.event_type` | string \| null | | `job.notify_webhook.deliveries` | integer | | `job.links` | object | | `job.links.self` | string | | `job.links.results` | string | | `job.links.cancel` | string \| null | | `results[]` | object[] | | `results[]` | object | | `results[].index` | integer | | `results[].status` | string | | `results[].reference` | string \| null | | `results[].input` | unknown | | `results[].data` | object \| null | | `results[].error` | object | | `results[].error.code` | string | | `results[].error.message` | string | | `results[].error.retryable` | boolean | | `results[].credits` | object | | `results[].credits.charged` | integer | | `results[].credits.refunded` | integer | | `limit` | integer | | `has_more` | boolean | | `next_cursor` | string \| null | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/jobs/string/results?limit=25&cursor=example" ``` ```javascript const response = await fetch("https://domscan.net/v1/jobs/string/results?limit=25&cursor=example", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/jobs/string/results?limit=25&cursor=example", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/jobs/string/results?limit=25&cursor=example", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/jobs/string/results?limit=25&cursor=example") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "job": { "id": "example-id", "kind": "batch", "status": "queued", "native_status": "queued", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "progress": { "total": 1, "done": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "credits": { "charged": 1, "refunded": 1 }, "notify_webhook": { "endpoint_id": "example", "status": "waiting", "event_type": "job.completed", "deliveries": 1 }, "links": { "self": "https://example.com", "results": "https://example.com", "cancel": "https://example.com" } }, "results": [ { "index": 1, "status": "pending", "reference": "example", "input": "example", "data": {}, "error": { "code": "example", "message": "Request completed", "retryable": false }, "credits": { "charged": 1, "refunded": 1 } } ], "limit": 1, "has_more": false, "next_cursor": "example" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `404` Not Found - `410` HTTP 410 - `429` Too Many Requests ## POST `/v1/jobs/:job_id/cancel` Operation: `cancelJob` Credits and authentication: Free Authentication required POST /v1/jobs/:job_id/cancel Credits: 0 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | job_id | string | required | #### Response fields | Field | Type | | --- | --- | | `job` | object | | `job.id` | string | | `job.kind` | string | | `job.status` | string | | `job.native_status` | string | | `job.created_at` | string \| null | | `job.updated_at` | string \| null | | `job.started_at` | string \| null | | `job.completed_at` | string \| null | | `job.results_expires_at` | string \| null | | `job.progress` | object | | `job.progress.total` | integer | | `job.progress.done` | integer | | `job.progress.succeeded` | integer | | `job.progress.failed` | integer | | `job.progress.cancelled` | integer | | `job.credits` | object | | `job.credits.charged` | integer | | `job.credits.refunded` | integer | | `job.notify_webhook` | object | | `job.notify_webhook.endpoint_id` | string \| null | | `job.notify_webhook.status` | string | | `job.notify_webhook.event_type` | string \| null | | `job.notify_webhook.deliveries` | integer | | `job.links` | object | | `job.links.self` | string | | `job.links.results` | string | | `job.links.cancel` | string \| null | | `cancellation` | string | #### Example request ```bash curl -X POST "https://domscan.net/v1/jobs/string/cancel" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{}' ``` ```javascript const response = await fetch("https://domscan.net/v1/jobs/string/cancel", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/jobs/string/cancel", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={}, ) print(response.json()) ``` ```go package main func main() { body := strings.NewReader(`{}`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/jobs/string/cancel", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/jobs/string/cancel") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({}) #### Example response ```json { "job": { "id": "example-id", "kind": "batch", "status": "queued", "native_status": "queued", "created_at": "2026-08-27T12:00:00Z", "updated_at": "2026-08-27T12:00:00Z", "started_at": "2026-08-27T12:00:00Z", "completed_at": "2026-08-27T12:00:00Z", "results_expires_at": "2026-08-27T12:00:00Z", "progress": { "total": 1, "done": 1, "succeeded": 1, "failed": 1, "cancelled": 1 }, "credits": { "charged": 1, "refunded": 1 }, "notify_webhook": { "endpoint_id": "example", "status": "waiting", "event_type": "job.completed", "deliveries": 1 }, "links": { "self": "https://example.com", "results": "https://example.com", "cancel": "https://example.com" } }, "cancellation": "accepted" } ``` #### HTTP status codes - `200` OK - `202` Accepted - `401` Unauthorized - `404` Not Found - `409` HTTP 409 - `429` Too Many Requests ## POST `/v1/estimate` Operation: `estimateRequestCost` Credits and authentication: Free Authentication required POST /v1/estimate Credits: 0 #### Body parameters | Parameter | Type | required | | --- | --- | --- | | method | string Allowed values `GET`, `POST`, `PUT`, `PATCH`, `DELETE` | required | | path | string | required | | query | object | optional | | body | unknown | optional | #### Response fields | Field | Type | | --- | --- | | `credits` | integer | | `breakdown[]` | object[] | | `breakdown[]` | object | | `breakdown[].component` | string | | `breakdown[].quantity` | integer | | `breakdown[].unit_credits` | number | | `breakdown[].credits` | integer | | `notes[]` | string[] | | `maximum` | boolean | | `rejected` | boolean | | `billing_model` | string | | `endpoint` | object | | `endpoint.method` | string | | `endpoint.path` | string | | `dry_run` | boolean | #### Example request ```bash curl -X POST "https://domscan.net/v1/estimate" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "method": "POST", "path": "/v1/value/bulk", "body": { "domains": [ "example.com", "example.org", "example.net" ] } }' ``` ```javascript const response = await fetch("https://domscan.net/v1/estimate", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "method": "POST", "path": "/v1/value/bulk", "body": { "domains": [ "example.com", "example.org", "example.net" ] } }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/estimate", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "method": "POST", "path": "/v1/value/bulk", "body": { "domains": [ "example.com", "example.org", "example.net", ], }, }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "method": "POST", "path": "/v1/value/bulk", "body": { "domains": [ "example.com", "example.org", "example.net" ] } }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/estimate", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/estimate") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "method" => "POST", "path" => "/v1/value/bulk", "body" => { "domains" => [ "example.com", "example.org", "example.net" ] } }) response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "credits": 6, "breakdown": [ { "component": "items", "quantity": 3, "unit_credits": 2, "credits": 6 } ], "notes": [ "Requests rejected with a 4xx status or failing with a 5xx status are refunded automatically." ], "maximum": false, "rejected": false, "endpoint": { "method": "POST", "path": "/v1/value/bulk" }, "billing_model": "per_item" } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker) --- Source: https://domscan.net/docs/products/workflow-recipes # Workflow recipes API Pre-built API workflows for common domain intelligence tasks. Each recipe combines multiple endpoints to accomplish a specific goal. Use this reference to choose an operation and integrate its documented response contract. [View product page](https://domscan.net/workflow-recipes-api) ## Operations GET `/v1/recipes/due-diligence` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeDueDiligence) GET `/v1/recipes/brand-launch` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeBrandLaunch) GET `/v1/recipes/threat-assessment` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeThreatAssessment) GET `/v1/recipes/domain-finder` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeDomainFinder) GET `/v1/recipes/competitor-intel` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeCompetitorIntel) GET `/v1/recipes/portfolio-audit` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipePortfolioAudit) POST `/v1/recipes/portfolio-audit` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipePortfolioAuditPost) GET `/v1/recipes/email-deliverability` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeEmailDeliverability) GET `/v1/recipes/dns-migration` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeDnsMigration) GET `/v1/recipes/infrastructure-discovery` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeInfrastructureDiscovery) GET `/v1/recipes/defensive-registration` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipeDefensiveRegistration) GET `/v1/recipes/phishing-investigation` [View API reference](https://domscan.net/docs/products/workflow-recipes#recipePhishingInvestigation) ## GET `/v1/recipes/due-diligence` Operation: `recipeDueDiligence` Credits and authentication: 12 Authentication required GET /v1/recipes/due-diligence Credits: 12 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | include_competitors | boolean Default `false` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.summary` | object | | `data.summary.recommendation` | string | | `data.summary.confidence_score` | number | | `data.summary.key_findings[]` | string[] | | `data.summary.risk_factors[]` | string[] | | `data.registration` | object | | `data.registration.registrar` | string | | `data.registration.created_date` | string | | `data.registration.expiry_date` | string | | `data.registration.updated_date` | string | | `data.registration.age_years` | number | | `data.registration.days_until_expiry` | number | | `data.registration.status[]` | string[] | | `data.registration.nameservers[]` | string[] | | `data.registration.dnssec` | boolean | | `data.registration.privacy_protected` | boolean | | `data.valuation` | object | | `data.valuation.estimate_low` | number | | `data.valuation.estimate_mid` | number | | `data.valuation.estimate_high` | number | | `data.valuation.currency` | string | | `data.valuation.confidence` | number | | `data.valuation.factors` | object | | `data.valuation.factors.length` | number | | `data.valuation.factors.tld` | string | | `data.valuation.factors.brandability` | number | | `data.health` | object | | `data.health.score` | number | | `data.health.grade` | string | | `data.health.dns_configured` | boolean | | `data.health.ssl_valid` | boolean | | `data.health.email_deliverable` | boolean | | `data.health.warnings[]` | string[] | | `data.security` | object | | `data.security.reputation_score` | number | | `data.security.reputation_grade` | string | | `data.security.risk_level` | string | | `data.security.blacklisted` | boolean | | `data.security.blacklist_details[]` | array | | `data.brand_protection` | object | | `data.brand_protection.typo_score` | number | | `data.brand_protection.typo_grade` | string | | `data.brand_protection.variants_registered` | number | | `data.brand_protection.high_risk_variants` | number | | `data.pricing` | object | | `data.pricing.best_price` | number | | `data.pricing.best_registrar` | string | | `data.pricing.all_prices[]` | object[] | | `data.pricing.all_prices[]` | object | | `data.pricing.all_prices[].registrar` | string | | `data.pricing.all_prices[].price` | number | | `data.pricing.all_prices[].currency` | string | | `data.action_items[]` | object[] | | `data.action_items[]` | object | | `data.action_items[].priority` | string | | `data.action_items[].category` | string | | `data.action_items[].action` | string | | `data.action_items[].details` | string | | `data.action_items[].estimated_impact` | string | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/due-diligence?domain=example.com&include_competitors=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/due-diligence?domain=example.com&include_competitors=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/due-diligence?domain=example.com&include_competitors=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/due-diligence?domain=example.com&include_competitors=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/due-diligence?domain=example.com&include_competitors=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "example.com", "summary": { "recommendation": "buy", "confidence_score": 88, "key_findings": [ "Established registration history", "Clean reputation" ], "risk_factors": [ "DNSSEC not enabled" ] }, "registration": { "registrar": "Example Registrar", "created_date": "2019-03-11", "expiry_date": "2027-03-11", "updated_date": "2026-03-10", "age_years": 7, "days_until_expiry": 330, "status": [ "active", "clientTransferProhibited" ], "nameservers": [ "ns1.example.net", "ns2.example.net" ], "dnssec": false, "privacy_protected": true }, "valuation": { "estimate_low": 1800, "estimate_mid": 3500, "estimate_high": 5200, "currency": "USD", "confidence": 0.72, "factors": { "length": 11, "tld": "com", "brandability": 0.81 } }, "health": { "score": 84, "grade": "A", "dns_configured": true, "ssl_valid": true, "email_deliverable": true, "warnings": [ "DNSSEC not enabled" ] }, "security": { "reputation_score": 91, "reputation_grade": "A", "risk_level": "low", "blacklisted": false, "blacklist_details": [] }, "brand_protection": { "typo_score": 78, "typo_grade": "B", "variants_registered": 2, "high_risk_variants": 1 }, "pricing": { "best_price": 9.99, "best_registrar": "cloudflare", "all_prices": [ { "registrar": "cloudflare", "price": 9.99, "currency": "USD" } ] }, "action_items": [ { "priority": "medium", "category": "security", "action": "Enable DNSSEC", "details": "Improve zone integrity for resolvers.", "estimated_impact": "Lower spoofing risk" } ] }, "meta": { "recipe_name": "domain-due-diligence", "credits_used": 12, "credits_saved": 6, "duration_ms": 742, "components_called": [ "availability", "whois", "valuation", "health", "reputation", "typosquatting", "pricing" ], "cached_components": [ "pricing" ], "timestamp": "2026-04-15T09:30:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/brand-launch` Operation: `recipeBrandLaunch` Credits and authentication: 10 Authentication required GET /v1/recipes/brand-launch Credits: 10 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | brand_name | string | optional | | platforms | string | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.brand_name` | string | | `data.readiness_score` | number | | `data.status` | string | | `data.checklist` | object | | `data.checklist.domain_controlled` | object | | `data.checklist.domain_controlled.name` | string | | `data.checklist.domain_controlled.status` | string | | `data.checklist.domain_controlled.details` | string | | `data.checklist.ssl_configured` | object | | `data.checklist.ssl_configured.name` | string | | `data.checklist.ssl_configured.status` | string | | `data.checklist.ssl_configured.details` | string | | `data.checklist.dns_configured` | object | | `data.checklist.dns_configured.name` | string | | `data.checklist.dns_configured.status` | string | | `data.checklist.dns_configured.details` | string | | `data.checklist.email_auth` | object | | `data.checklist.email_auth.name` | string | | `data.checklist.email_auth.status` | string | | `data.checklist.email_auth.score` | number | | `data.checklist.email_auth.details` | string | | `data.checklist.email_auth.action` | string | | `data.checklist.social_handles` | object | | `data.checklist.social_handles.name` | string | | `data.checklist.social_handles.status` | string | | `data.checklist.social_handles.score` | number | | `data.checklist.social_handles.details` | string | | `data.checklist.brand_protection` | object | | `data.checklist.brand_protection.name` | string | | `data.checklist.brand_protection.status` | string | | `data.checklist.brand_protection.score` | number | | `data.checklist.brand_protection.details` | string | | `data.checklist.reputation_clean` | object | | `data.checklist.reputation_clean.name` | string | | `data.checklist.reputation_clean.status` | string | | `data.checklist.reputation_clean.details` | string | | `data.checklist.brand_quality` | object | | `data.checklist.brand_quality.name` | string | | `data.checklist.brand_quality.status` | string | | `data.checklist.brand_quality.score` | number | | `data.checklist.brand_quality.details` | string | | `data.social_availability[]` | object[] | | `data.social_availability[]` | object | | `data.social_availability[].platform` | string | | `data.social_availability[].available` | boolean | | `data.social_availability[].url` | string | | `data.typo_threats` | object | | `data.typo_threats.total_variants` | number | | `data.typo_threats.registered_threats` | number | | `data.typo_threats.high_risk_count` | number | | `data.brand_score` | object | | `data.brand_score.overall` | number | | `data.brand_score.pronounceability` | number | | `data.brand_score.memorability` | number | | `data.brand_score.spelling_ease` | number | | `data.action_items[]` | object[] | | `data.action_items[]` | object | | `data.action_items[].priority` | string | | `data.action_items[].category` | string | | `data.action_items[].action` | string | | `data.action_items[].details` | string | | `data.action_items[].estimated_impact` | string | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | array | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/brand-launch?domain=example.com&brand_name=Example&platforms=github%2Ctwitter" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/brand-launch?domain=example.com&brand_name=Example&platforms=github%2Ctwitter", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/brand-launch?domain=example.com&brand_name=Example&platforms=github%2Ctwitter", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/brand-launch?domain=example.com&brand_name=Example&platforms=github%2Ctwitter", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/brand-launch?domain=example.com&brand_name=Example&platforms=github%2Ctwitter") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "launchbrand.com", "brand_name": "Launch Brand", "readiness_score": 82, "status": "ready", "checklist": { "domain_controlled": { "name": "Domain Ownership", "status": "pass", "details": "Domain is registered" }, "ssl_configured": { "name": "SSL Certificate", "status": "pass", "details": "HTTPS is working" }, "dns_configured": { "name": "DNS Configuration", "status": "pass", "details": "DNS records configured" }, "email_auth": { "name": "Email Authentication", "status": "warning", "score": 66, "details": "Missing: DMARC", "action": "Configure DMARC" }, "social_handles": { "name": "Social Handles", "status": "warning", "score": 50, "details": "2 of 4 handles available" }, "brand_protection": { "name": "Brand Protection", "status": "warning", "score": 71, "details": "1 high-risk typo variant available" }, "reputation_clean": { "name": "Reputation", "status": "pass", "details": "Clean reputation" }, "brand_quality": { "name": "Brand Quality", "status": "pass", "score": 84, "details": "Strong memorability and spelling ease" } }, "social_availability": [ { "platform": "github", "available": true, "url": "https://github.com/launchbrand" }, { "platform": "twitter", "available": false } ], "typo_threats": { "total_variants": 48, "registered_threats": 2, "high_risk_count": 1 }, "brand_score": { "overall": 84, "pronounceability": 80, "memorability": 86, "spelling_ease": 88 }, "action_items": [ { "priority": "high", "category": "email", "action": "Configure DMARC", "details": "Complete the authentication trio before launch.", "estimated_impact": "Higher inbox placement" } ] }, "meta": { "recipe_name": "brand-launch-readiness", "credits_used": 10, "credits_saved": 4, "duration_ms": 581, "components_called": [ "availability", "health", "dns_security", "reputation", "typosquatting", "scoring", "social" ], "cached_components": [], "timestamp": "2026-04-15T09:42:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/threat-assessment` Operation: `recipeThreatAssessment` Credits and authentication: 18 Authentication required GET /v1/recipes/threat-assessment Credits: 18 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | analyze_threats | boolean Default `true` | optional | | max_threats | integer Default `10` | optional | | include_evidence | boolean Default `true` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.summary` | object | | `data.summary.risk_level` | string | | `data.summary.overall_score` | number | | `data.summary.total_variants_generated` | number | | `data.summary.variants_registered` | number | | `data.summary.active_threats` | number | | `data.summary.suspicious_activity` | number | | `data.protection_score` | object | | `data.protection_score.score` | number | | `data.protection_score.grade` | string | | `data.protection_score.vulnerabilities[]` | object[] | | `data.protection_score.vulnerabilities[]` | object | | `data.protection_score.vulnerabilities[].category` | string | | `data.protection_score.vulnerabilities[].count` | number | | `data.protection_score.vulnerabilities[].risk` | string | | `data.protection_score.vulnerabilities[].description` | string | | `data.threats[]` | object[] | | `data.threats[]` | object | | `data.threats[].domain` | string | | `data.threats[].threat_type` | string | | `data.threats[].risk_level` | string | | `data.threats[].registered` | boolean | | `data.threats[].registration` | object | | `data.threats[].registration.registrar` | string | | `data.threats[].registration.created_date` | string | | `data.threats[].registration.privacy_protected` | boolean | | `data.threats[].infrastructure` | object | | `data.threats[].infrastructure.ip` | string | | `data.threats[].infrastructure.hosting_provider` | string | | `data.threats[].infrastructure.country` | string | | `data.threats[].indicators` | object | | `data.threats[].indicators.has_mx_records` | boolean | | `data.threats[].indicators.has_website` | boolean | | `data.threats[].indicators.ssl_valid` | boolean | | `data.threats[].indicators.reputation_flags[]` | string[] | | `data.threats[].recommendation` | string | | `data.recommendations[]` | string[] | | `data.action_items[]` | object[] | | `data.action_items[]` | object | | `data.action_items[].priority` | string | | `data.action_items[].category` | string | | `data.action_items[].action` | string | | `data.action_items[].details` | string | | `data.action_items[].estimated_impact` | string | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/threat-assessment?domain=example.com&analyze_threats=true&max_threats=10&include_evidence=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/threat-assessment?domain=example.com&analyze_threats=true&max_threats=10&include_evidence=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/threat-assessment?domain=example.com&analyze_threats=true&max_threats=10&include_evidence=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/threat-assessment?domain=example.com&analyze_threats=true&max_threats=10&include_evidence=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/threat-assessment?domain=example.com&analyze_threats=true&max_threats=10&include_evidence=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "brand.com", "summary": { "risk_level": "high", "overall_score": 61, "total_variants_generated": 120, "variants_registered": 14, "active_threats": 3, "suspicious_activity": 2 }, "protection_score": { "score": 73, "grade": "B", "vulnerabilities": [ { "category": "homoglyph", "count": 3, "risk": "high", "description": "Lookalike Unicode variants are registered." } ] }, "threats": [ { "domain": "brancd.com", "threat_type": "typosquatting", "risk_level": "high", "registered": true, "registration": { "registrar": "Example Registrar", "created_date": "2026-01-10", "privacy_protected": true }, "infrastructure": { "ip": "198.51.100.21", "hosting_provider": "Example Hosting", "country": "US" }, "indicators": { "has_mx_records": true, "has_website": true, "ssl_valid": false, "reputation_flags": [ "recent_registration", "parked" ] }, "recommendation": "Investigate hosting and submit abuse report." } ], "recommendations": [ "Monitor newly registered typo variants.", "Escalate active lookalike websites to brand protection." ], "action_items": [ { "priority": "critical", "category": "brand-protection", "action": "Investigate high-risk typo domains", "details": "Three active websites are impersonating the brand.", "estimated_impact": "Reduce phishing exposure" } ] }, "meta": { "recipe_name": "threat-assessment", "credits_used": 18, "credits_saved": 22, "duration_ms": 934, "components_called": [ "typosquatting", "availability", "whois", "health", "reputation" ], "cached_components": [ "availability" ], "timestamp": "2026-04-15T10:02:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/domain-finder` Operation: `recipeDomainFinder` Credits and authentication: 12 Authentication required GET /v1/recipes/domain-finder Credits: 12 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | keywords | string | required | | tlds | string | optional | | style | string Allowed values `brandable`, `keyword-rich`, `short` | optional | | max_length | integer | optional | | language | string Allowed values `en`, `zh`, `es`, `ja`, `de`, `fr`, `pt`, `it`, `ko`, `ru`, `ar`, `hi`, `bn`, `id`, `ms`, `th`, `vi`, `tr`, `pl`, `nl`, `sv`, `da`, `no`, `fi`, `el`, `cs`, `hu`, `ro`, `uk`, `he` Default `en` | optional | | limit | integer Default `20` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.results[]` | object[] | | `data.results[]` | object | | `data.results[].domain` | string | | `data.results[].available` | boolean | | `data.results[].brand_score` | number | | `data.results[].value_estimate` | object | | `data.results[].value_estimate.low` | number | | `data.results[].value_estimate.mid` | number | | `data.results[].value_estimate.high` | number | | `data.results[].registration_price` | number | | `data.results[].best_registrar` | string | | `data.results[].social_availability` | object | | `data.results[].social_availability.github` | boolean | | `data.results[].social_availability.twitter` | boolean | | `data.results[].recommendation_score` | number | | `data.results[].notes[]` | string[] | | `data.filters_applied` | object | | `data.filters_applied.tlds[]` | string[] | | `data.filters_applied.style` | string | | `data.filters_applied.max_length` | number | | `data.alternatives_considered` | number | | `data.search_criteria` | object | | `data.search_criteria.keywords[]` | string[] | | `data.search_criteria.tlds[]` | string[] | | `data.search_criteria.style` | string | | `data.search_criteria.max_length` | number | | `data.search_criteria.budget` | object | | `data.search_criteria.budget.max` | number | | `data.search_criteria.budget.currency` | string | | `data.search_criteria.require_social[]` | string[] | | `data.search_criteria.limit` | number | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/domain-finder?keywords=startup%2Cbrand&tlds=com%2Cio&style=brandable&max_length=15&language=en&limit=10" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/domain-finder?keywords=startup%2Cbrand&tlds=com%2Cio&style=brandable&max_length=15&language=en&limit=10", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/domain-finder?keywords=startup%2Cbrand&tlds=com%2Cio&style=brandable&max_length=15&language=en&limit=10", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/domain-finder?keywords=startup%2Cbrand&tlds=com%2Cio&style=brandable&max_length=15&language=en&limit=10", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/domain-finder?keywords=startup%2Cbrand&tlds=com%2Cio&style=brandable&max_length=15&language=en&limit=10") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "results": [ { "domain": "launchgrid.com", "available": true, "brand_score": 86, "value_estimate": { "low": 400, "mid": 1200, "high": 2800 }, "registration_price": 10.99, "best_registrar": "porkbun", "social_availability": { "github": true, "twitter": false }, "recommendation_score": 92, "notes": [ "Style: brandable", "Within budget" ] } ], "filters_applied": { "tlds": [ "com", "io" ], "style": "brandable", "max_length": 12 }, "alternatives_considered": 42, "search_criteria": { "keywords": [ "launch", "grid" ], "tlds": [ "com", "io" ], "style": "brandable", "max_length": 12, "budget": { "max": 20, "currency": "USD" }, "require_social": [ "github", "twitter" ], "limit": 10 } }, "meta": { "recipe_name": "domain-finder", "credits_used": 12, "credits_saved": 13, "duration_ms": 611, "components_called": [ "suggest", "availability", "valuation", "scoring", "social", "pricing" ], "cached_components": [ "pricing" ], "timestamp": "2026-04-15T10:11:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/competitor-intel` Operation: `recipeCompetitorIntel` Credits and authentication: 15 Authentication required GET /v1/recipes/competitor-intel Credits: 15 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | discover_subdomains | boolean Default `true` | optional | | analyze_infrastructure | boolean Default `true` | optional | | analyze_email | boolean Default `true` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.company` | object | | `data.company.name` | string | | `data.company.industry` | string | | `data.company.description` | string | | `data.infrastructure` | object | | `data.infrastructure.hosting` | string | | `data.infrastructure.cdn` | string | | `data.infrastructure.dns_provider` | string | | `data.infrastructure.email_provider` | string | | `data.infrastructure.ip_addresses[]` | string[] | | `data.technology` | object | | `data.technology.cms` | null | | `data.technology.frameworks[]` | string[] | | `data.technology.analytics[]` | string[] | | `data.technology.marketing[]` | string[] | | `data.technology.all_detected[]` | string[] | | `data.digital_footprint` | object | | `data.digital_footprint.subdomains_found[]` | string[] | | `data.digital_footprint.ssl_certificates` | number | | `data.digital_footprint.email_security_grade` | string | | `data.insights[]` | string[] | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/competitor-intel?domain=example.com&discover_subdomains=true&analyze_infrastructure=true&analyze_email=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/competitor-intel?domain=example.com&discover_subdomains=true&analyze_infrastructure=true&analyze_email=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/competitor-intel?domain=example.com&discover_subdomains=true&analyze_infrastructure=true&analyze_email=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/competitor-intel?domain=example.com&discover_subdomains=true&analyze_infrastructure=true&analyze_email=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/competitor-intel?domain=example.com&discover_subdomains=true&analyze_infrastructure=true&analyze_email=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "competitor.com", "company": { "name": "Competitor Inc.", "industry": "SaaS", "description": "B2B workflow platform" }, "infrastructure": { "hosting": "Vercel", "cdn": "Cloudflare", "dns_provider": "Cloudflare", "email_provider": "Google Workspace", "ip_addresses": [ "198.51.100.11", "198.51.100.12" ] }, "technology": { "cms": null, "frameworks": [ "Next.js" ], "analytics": [ "Google Analytics" ], "marketing": [ "HubSpot" ], "all_detected": [ "Cloudflare", "Next.js", "HubSpot", "Google Analytics" ] }, "digital_footprint": { "subdomains_found": [ "www", "app", "api", "status" ], "ssl_certificates": 5, "email_security_grade": "A" }, "insights": [ "Cloudflare is fronting the main web stack.", "Separate status infrastructure is publicly exposed." ] }, "meta": { "recipe_name": "competitor-intelligence", "credits_used": 15, "credits_saved": 5, "duration_ms": 915, "components_called": [ "whois", "dns", "dns-security", "tech", "subdomains", "certificates", "ip" ], "cached_components": [ "dns" ], "timestamp": "2026-04-15T10:22:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/portfolio-audit` Operation: `recipePortfolioAudit` Credits and authentication: 25 Authentication required GET /v1/recipes/portfolio-audit Credits: 25 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domains | string | required | | include_valuation | boolean Default `true` | optional | | include_health | boolean Default `true` | optional | | include_pricing | boolean Default `true` | optional | | alert_expiring_days | integer Default `90` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.summary` | object | | `data.summary.total_domains` | number | | `data.summary.total_value_low` | number | | `data.summary.total_value_high` | number | | `data.summary.average_health_score` | number | | `data.summary.expiring_soon` | number | | `data.summary.renewal_cost_annual` | number | | `data.alerts[]` | object[] | | `data.alerts[]` | object | | `data.alerts[].domain` | string | | `data.alerts[].type` | string | | `data.alerts[].severity` | string | | `data.alerts[].message` | string | | `data.alerts[].action` | string | | `data.optimization` | object | | `data.optimization.registrar_consolidation` | object | | `data.optimization.registrar_consolidation.current_registrars` | number | | `data.optimization.registrar_consolidation.recommendation` | string | | `data.optimization.registrar_consolidation.potential_savings` | number | | `data.optimization.underperforming[]` | string[] | | `data.optimization.top_valuable[]` | string[] | | `data.domains[]` | object[] | | `data.domains[]` | object | | `data.domains[].domain` | string | | `data.domains[].status` | string | | `data.domains[].value_estimate` | object | | `data.domains[].value_estimate.low` | number | | `data.domains[].value_estimate.mid` | number | | `data.domains[].value_estimate.high` | number | | `data.domains[].health_score` | number | | `data.domains[].health_grade` | string | | `data.domains[].expiry_date` | string | | `data.domains[].days_until_expiry` | number | | `data.domains[].renewal_price` | number | | `data.domains[].issues[]` | array | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/portfolio-audit?domains=example.com%2Cexample.net&include_valuation=true&include_health=true&include_pricing=true&alert_expiring_days=90" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/portfolio-audit?domains=example.com%2Cexample.net&include_valuation=true&include_health=true&include_pricing=true&alert_expiring_days=90", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/portfolio-audit?domains=example.com%2Cexample.net&include_valuation=true&include_health=true&include_pricing=true&alert_expiring_days=90", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/portfolio-audit?domains=example.com%2Cexample.net&include_valuation=true&include_health=true&include_pricing=true&alert_expiring_days=90", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/portfolio-audit?domains=example.com%2Cexample.net&include_valuation=true&include_health=true&include_pricing=true&alert_expiring_days=90") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "summary": { "total_domains": 3, "total_value_low": 3200, "total_value_high": 12400, "average_health_score": 78, "expiring_soon": 1, "renewal_cost_annual": 98.4 }, "alerts": [ { "domain": "brandold.com", "type": "expiration", "severity": "high", "message": "Expires in 12 days.", "action": "Renew immediately" } ], "optimization": { "registrar_consolidation": { "current_registrars": 3, "recommendation": "Move long-tail domains to a single low-cost registrar.", "potential_savings": 48 }, "underperforming": [ "brandold.com" ], "top_valuable": [ "brand.com" ] }, "domains": [ { "domain": "brand.com", "status": "owned", "value_estimate": { "low": 2500, "mid": 4600, "high": 9000 }, "health_score": 92, "health_grade": "A", "expiry_date": "2027-02-01", "days_until_expiry": 292, "renewal_price": 12.99, "issues": [] } ] }, "meta": { "recipe_name": "portfolio-audit", "credits_used": 25, "credits_saved": 275, "duration_ms": 1298, "components_called": [ "availability", "whois", "valuation", "health", "pricing" ], "cached_components": [ "valuation" ], "timestamp": "2026-04-15T10:31:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## POST `/v1/recipes/portfolio-audit` Operation: `recipePortfolioAuditPost` Credits and authentication: 25 Authentication required POST /v1/recipes/portfolio-audit Credits: 25 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | dry_run | string Allowed values `true` | optional | #### Body parameters | Parameter | Type | required | | --- | --- | --- | | domains | string[] | required | | include_valuation | boolean Default `true` | optional | | include_health | boolean Default `true` | optional | | include_pricing | boolean Default `true` | optional | | alert_expiring_days | integer Default `90` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.summary` | object | | `data.summary.total_domains` | number | | `data.summary.total_value_low` | number | | `data.summary.total_value_high` | number | | `data.summary.average_health_score` | number | | `data.summary.expiring_soon` | number | | `data.summary.renewal_cost_annual` | number | | `data.alerts[]` | object[] | | `data.alerts[]` | object | | `data.alerts[].domain` | string | | `data.alerts[].type` | string | | `data.alerts[].severity` | string | | `data.alerts[].message` | string | | `data.alerts[].action` | string | | `data.optimization` | object | | `data.optimization.registrar_consolidation` | object | | `data.optimization.registrar_consolidation.current_registrars` | number | | `data.optimization.registrar_consolidation.recommendation` | string | | `data.optimization.registrar_consolidation.potential_savings` | number | | `data.optimization.underperforming[]` | string[] | | `data.optimization.top_valuable[]` | string[] | | `data.domains[]` | object[] | | `data.domains[]` | object | | `data.domains[].domain` | string | | `data.domains[].status` | string | | `data.domains[].value_estimate` | object | | `data.domains[].value_estimate.low` | number | | `data.domains[].value_estimate.mid` | number | | `data.domains[].value_estimate.high` | number | | `data.domains[].health_score` | number | | `data.domains[].health_grade` | string | | `data.domains[].expiry_date` | string | | `data.domains[].days_until_expiry` | number | | `data.domains[].renewal_price` | number | | `data.domains[].issues[]` | array | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -X POST "https://domscan.net/v1/recipes/portfolio-audit" \ -H "Content-Type: application/json" \ -H "X-API-Key: $DOMSCAN_API_KEY" \ -d '{ "domains": [ "example.com", "example.org", "example.net" ], "include_valuation": true, "include_health": true, "include_pricing": false, "alert_expiring_days": 60 }' ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/portfolio-audit", { method: "POST", headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ "domains": [ "example.com", "example.org", "example.net" ], "include_valuation": true, "include_health": true, "include_pricing": false, "alert_expiring_days": 60 }), }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.post( "https://domscan.net/v1/recipes/portfolio-audit", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, json={ "domains": [ "example.com", "example.org", "example.net", ], "include_valuation": True, "include_health": True, "include_pricing": False, "alert_expiring_days": 60, }, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{ "domains": [ "example.com", "example.org", "example.net" ], "include_valuation": true, "include_health": true, "include_pricing": false, "alert_expiring_days": 60 }`) req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/recipes/portfolio-audit", body) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) req.Header.Set("Content-Type", "application/json") ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/portfolio-audit") request = Net::HTTP::Post.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") request["Content-Type"] = "application/json" request.body = JSON.generate({ "domains" => [ "example.com", "example.org", "example.net" ], "include_valuation" => true, "include_health" => true, "include_pricing" => false, "alert_expiring_days" => 60 }) #### Example response ```json { "success": true, "data": { "summary": { "total_domains": 3, "total_value_low": 3200, "total_value_high": 12400, "average_health_score": 78, "expiring_soon": 1, "renewal_cost_annual": 98.4 }, "alerts": [ { "domain": "brandold.com", "type": "expiration", "severity": "high", "message": "Expires in 12 days.", "action": "Renew immediately" } ], "optimization": { "registrar_consolidation": { "current_registrars": 3, "recommendation": "Move long-tail domains to a single low-cost registrar.", "potential_savings": 48 }, "underperforming": [ "brandold.com" ], "top_valuable": [ "brand.com" ] }, "domains": [ { "domain": "brand.com", "status": "owned", "value_estimate": { "low": 2500, "mid": 4600, "high": 9000 }, "health_score": 92, "health_grade": "A", "expiry_date": "2027-02-01", "days_until_expiry": 292, "renewal_price": 12.99, "issues": [] } ] }, "meta": { "recipe_name": "portfolio-audit", "credits_used": 25, "credits_saved": 275, "duration_ms": 1298, "components_called": [ "availability", "whois", "valuation", "health", "pricing" ], "cached_components": [ "valuation" ], "timestamp": "2026-04-15T10:31:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `409` HTTP 409 - `422` HTTP 422 - `429` Too Many Requests ## GET `/v1/recipes/email-deliverability` Operation: `recipeEmailDeliverability` Credits and authentication: 10 Authentication required GET /v1/recipes/email-deliverability Credits: 10 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | dkim_selectors | string | optional | | check_blacklists | boolean Default `true` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.grade` | string | | `data.score` | number | | `data.authentication` | object | | `data.authentication.spf` | object | | `data.authentication.spf.status` | string | | `data.authentication.spf.record` | string | | `data.authentication.spf.issues[]` | array | | `data.authentication.dkim` | object | | `data.authentication.dkim.status` | string | | `data.authentication.dkim.record` | string | | `data.authentication.dkim.issues[]` | string[] | | `data.authentication.dkim.recommendation` | string | | `data.authentication.dkim.selectors_found[]` | string[] | | `data.authentication.dmarc` | object | | `data.authentication.dmarc.status` | string | | `data.authentication.dmarc.record` | string | | `data.authentication.dmarc.issues[]` | string[] | | `data.authentication.dmarc.recommendation` | string | | `data.authentication.dmarc.policy` | string | | `data.infrastructure` | object | | `data.infrastructure.mx_servers[]` | string[] | | `data.infrastructure.ip_reputation` | string | | `data.infrastructure.shared_ip_risk` | string | | `data.blacklist_status` | object | | `data.blacklist_status.listed_on[]` | array | | `data.blacklist_status.clean` | boolean | | `data.action_items[]` | object[] | | `data.action_items[]` | object | | `data.action_items[].priority` | string | | `data.action_items[].category` | string | | `data.action_items[].action` | string | | `data.action_items[].details` | string | | `data.action_items[].estimated_impact` | string | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | array | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/email-deliverability?domain=example.com&dkim_selectors=default%2Cgoogle&check_blacklists=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/email-deliverability?domain=example.com&dkim_selectors=default%2Cgoogle&check_blacklists=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/email-deliverability?domain=example.com&dkim_selectors=default%2Cgoogle&check_blacklists=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/email-deliverability?domain=example.com&dkim_selectors=default%2Cgoogle&check_blacklists=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/email-deliverability?domain=example.com&dkim_selectors=default%2Cgoogle&check_blacklists=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "example.com", "grade": "B", "score": 74, "authentication": { "spf": { "status": "pass", "record": "v=spf1 include:_spf.google.com ~all", "issues": [] }, "dkim": { "status": "warning", "record": "selector discovery incomplete", "issues": [ "Only one selector found" ], "recommendation": "Add dedicated selectors for all providers", "selectors_found": [ "google" ] }, "dmarc": { "status": "warning", "record": "v=DMARC1; p=none; rua=mailto:dmarc@example.com", "issues": [ "Policy is monitoring-only" ], "recommendation": "Move to quarantine or reject", "policy": "none" } }, "infrastructure": { "mx_servers": [ "aspmx.l.google.com" ], "ip_reputation": "low", "shared_ip_risk": "medium" }, "blacklist_status": { "listed_on": [], "clean": true }, "action_items": [ { "priority": "high", "category": "email", "action": "Strengthen DMARC policy", "details": "Current DMARC policy is set to none.", "estimated_impact": "Better spoofing protection" } ] }, "meta": { "recipe_name": "email-deliverability", "credits_used": 10, "credits_saved": 5, "duration_ms": 662, "components_called": [ "dns-security", "dnsbl", "mx-analysis" ], "cached_components": [], "timestamp": "2026-04-15T10:43:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/dns-migration` Operation: `recipeDnsMigration` Credits and authentication: 7 Authentication required GET /v1/recipes/dns-migration Credits: 7 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | target_nameservers | string | optional | | critical_records | string | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.status` | string | | `data.current_configuration` | object | | `data.current_configuration.nameservers[]` | string[] | | `data.current_configuration.records` | object | | `data.current_configuration.records.A[]` | string[] | | `data.current_configuration.records.MX[]` | string[] | | `data.current_configuration.records.TXT[]` | string[] | | `data.current_configuration.email_auth` | object | | `data.current_configuration.email_auth.spf` | string | | `data.current_configuration.email_auth.dkim_selectors[]` | string[] | | `data.current_configuration.email_auth.dmarc` | string | | `data.migration_checklist[]` | object[] | | `data.migration_checklist[]` | object | | `data.migration_checklist[].record_type` | string | | `data.migration_checklist[].current_value` | string | | `data.migration_checklist[].action` | string | | `data.migration_checklist[].critical` | boolean | | `data.migration_checklist[].ttl` | number | | `data.warnings[]` | object[] | | `data.warnings[]` | object | | `data.warnings[].type` | string | | `data.warnings[].message` | string | | `data.warnings[].records[]` | string[] | | `data.estimated_propagation` | string | | `data.rollback_plan` | object | | `data.rollback_plan.keep_old_records_until` | string | | `data.rollback_plan.revert_steps[]` | string[] | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/dns-migration?domain=example.com&target_nameservers=ns1.newdns.net%2Cns2.newdns.net&critical_records=A%2CAAAA%2CMX" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/dns-migration?domain=example.com&target_nameservers=ns1.newdns.net%2Cns2.newdns.net&critical_records=A%2CAAAA%2CMX", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/dns-migration?domain=example.com&target_nameservers=ns1.newdns.net%2Cns2.newdns.net&critical_records=A%2CAAAA%2CMX", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/dns-migration?domain=example.com&target_nameservers=ns1.newdns.net%2Cns2.newdns.net&critical_records=A%2CAAAA%2CMX", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/dns-migration?domain=example.com&target_nameservers=ns1.newdns.net%2Cns2.newdns.net&critical_records=A%2CAAAA%2CMX") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "example.com", "status": "ready", "current_configuration": { "nameservers": [ "ns1.current-dns.net", "ns2.current-dns.net" ], "records": { "A": [ "198.51.100.8" ], "MX": [ "10 mail.example.com" ], "TXT": [ "v=spf1 include:_spf.google.com ~all" ] }, "email_auth": { "spf": "v=spf1 include:_spf.google.com ~all", "dkim_selectors": [ "google", "mail" ], "dmarc": "v=DMARC1; p=quarantine" } }, "migration_checklist": [ { "record_type": "MX", "current_value": "10 mail.example.com", "action": "migrate", "critical": true, "ttl": 3600 } ], "warnings": [ { "type": "ttl", "message": "High TTL values will slow cutover.", "records": [ "A", "MX" ] } ], "estimated_propagation": "4-8 hours", "rollback_plan": { "keep_old_records_until": "48-72 hours after migration", "revert_steps": [ "Keep screenshots of the current zone", "Restore old nameservers at the registrar if traffic fails" ] } }, "meta": { "recipe_name": "dns-migration", "credits_used": 7, "credits_saved": 5, "duration_ms": 734, "components_called": [ "dns", "dns-security", "ttl-analysis" ], "cached_components": [ "dns" ], "timestamp": "2026-04-15T10:54:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/infrastructure-discovery` Operation: `recipeInfrastructureDiscovery` Credits and authentication: 15 Authentication required GET /v1/recipes/infrastructure-discovery Credits: 15 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | domain | string | required | | depth | string Allowed values `quick`, `standard`, `deep` Default `standard` | optional | | include_historical | boolean Default `false` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.domain` | string | | `data.subdomains` | object | | `data.subdomains.count` | number | | `data.subdomains.items[]` | object[] | | `data.subdomains.items[]` | object | | `data.subdomains.items[].subdomain` | string | | `data.subdomains.items[].ip` | string | | `data.subdomains.items[].tech[]` | string[] | | `data.ip_addresses` | object | | `data.ip_addresses.unique_ips` | number | | `data.ip_addresses.items[]` | object[] | | `data.ip_addresses.items[]` | object | | `data.ip_addresses.items[].ip` | string | | `data.ip_addresses.items[].asn` | string | | `data.ip_addresses.items[].org` | string | | `data.ip_addresses.items[].country` | string | | `data.hosting` | object | | `data.hosting.providers[]` | string[] | | `data.hosting.regions[]` | string[] | | `data.related_domains[]` | string[] | | `data.technology_summary` | object | | `data.technology_summary.cms` | null | | `data.technology_summary.frameworks[]` | string[] | | `data.technology_summary.servers[]` | string[] | | `data.technology_summary.cdn` | string | | `data.attack_surface` | object | | `data.attack_surface.exposed_services[]` | string[] | | `data.attack_surface.potential_entry_points[]` | string[] | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | array | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/infrastructure-discovery?domain=example.com&depth=standard&include_historical=false" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/infrastructure-discovery?domain=example.com&depth=standard&include_historical=false", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/infrastructure-discovery?domain=example.com&depth=standard&include_historical=false", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/infrastructure-discovery?domain=example.com&depth=standard&include_historical=false", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/infrastructure-discovery?domain=example.com&depth=standard&include_historical=false") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "domain": "example.com", "subdomains": { "count": 4, "items": [ { "subdomain": "api.example.com", "ip": "198.51.100.44", "tech": [ "nginx", "Node.js" ] } ] }, "ip_addresses": { "unique_ips": 2, "items": [ { "ip": "198.51.100.44", "asn": "AS13335", "org": "Cloudflare, Inc.", "country": "US" } ] }, "hosting": { "providers": [ "Cloudflare", "Vercel" ], "regions": [ "US", "EU" ] }, "related_domains": [ "status-example.com" ], "technology_summary": { "cms": null, "frameworks": [ "Next.js" ], "servers": [ "nginx" ], "cdn": "Cloudflare" }, "attack_surface": { "exposed_services": [ "HTTPS", "API" ], "potential_entry_points": [ "api.example.com", "status.example.com" ] } }, "meta": { "recipe_name": "infrastructure-discovery", "credits_used": 15, "credits_saved": 10, "duration_ms": 1084, "components_called": [ "subdomains", "ip", "tech", "certificates" ], "cached_components": [], "timestamp": "2026-04-15T11:07:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/defensive-registration` Operation: `recipeDefensiveRegistration` Credits and authentication: 12 Authentication required GET /v1/recipes/defensive-registration Credits: 12 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | brand | string | required | | owned_domains | string | required | | priority_tlds | string | optional | | include_typos | boolean Default `true` | optional | | budget | number | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.brand` | string | | `data.summary` | object | | `data.summary.total_candidates` | number | | `data.summary.already_owned` | number | | `data.summary.available` | number | | `data.summary.registered_by_others` | number | | `data.summary.within_budget` | number | | `data.priority_registrations[]` | object[] | | `data.priority_registrations[]` | object | | `data.priority_registrations[].domain` | string | | `data.priority_registrations[].type` | string | | `data.priority_registrations[].available` | boolean | | `data.priority_registrations[].risk_if_unowned` | string | | `data.priority_registrations[].price` | number | | `data.priority_registrations[].registrar` | string | | `data.typo_threats[]` | object[] | | `data.typo_threats[]` | object | | `data.typo_threats[].domain` | string | | `data.typo_threats[].type` | string | | `data.typo_threats[].available` | boolean | | `data.typo_threats[].risk_if_unowned` | string | | `data.typo_threats[].price` | null | | `data.typo_threats[].registrar` | null | | `data.shopping_cart` | object | | `data.shopping_cart.domains[]` | string[] | | `data.shopping_cart.total_cost` | number | | `data.shopping_cart.within_budget` | boolean | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | string[] | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/defensive-registration?brand=acme&owned_domains=acme.com&priority_tlds=com&include_typos=true&budget=0.5" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/defensive-registration?brand=acme&owned_domains=acme.com&priority_tlds=com&include_typos=true&budget=0.5", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/defensive-registration?brand=acme&owned_domains=acme.com&priority_tlds=com&include_typos=true&budget=0.5", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/defensive-registration?brand=acme&owned_domains=acme.com&priority_tlds=com&include_typos=true&budget=0.5", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/defensive-registration?brand=acme&owned_domains=acme.com&priority_tlds=com&include_typos=true&budget=0.5") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") #### Example response ```json { "success": true, "data": { "brand": "acme", "summary": { "total_candidates": 18, "already_owned": 3, "available": 9, "registered_by_others": 6, "within_budget": 5 }, "priority_registrations": [ { "domain": "acme.io", "type": "tld_variant", "available": true, "risk_if_unowned": "high", "price": 39.99, "registrar": "porkbun" } ], "typo_threats": [ { "domain": "acm3.com", "type": "typo", "available": false, "risk_if_unowned": "high", "price": null, "registrar": null } ], "shopping_cart": { "domains": [ "acme.io", "acme.co" ], "total_cost": 63.98, "within_budget": true } }, "meta": { "recipe_name": "defensive-registration", "credits_used": 12, "credits_saved": 8, "duration_ms": 688, "components_called": [ "typosquatting", "availability", "pricing", "tld-intelligence" ], "cached_components": [ "pricing" ], "timestamp": "2026-04-15T11:16:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## GET `/v1/recipes/phishing-investigation` Operation: `recipePhishingInvestigation` Credits and authentication: 12 Authentication required GET /v1/recipes/phishing-investigation Credits: 12 #### Query parameters | Parameter | Type | required | | --- | --- | --- | | suspicious_domain | string | required | | legitimate_domain | string | optional | | collect_evidence | boolean Default `true` | optional | | dry_run | string Allowed values `true` | optional | #### Response fields | Field | Type | | --- | --- | | `success` | boolean | | `data` | object | | `data.suspicious_domain` | string | | `data.legitimate_domain` | string | | `data.verdict` | string | | `data.confidence` | number | | `data.indicators` | object | | `data.indicators.typosquatting` | object | | `data.indicators.typosquatting.detected` | boolean | | `data.indicators.typosquatting.technique` | string | | `data.indicators.domain_age` | object | | `data.indicators.domain_age.days` | number | | `data.indicators.domain_age.risk` | string | | `data.indicators.registration` | object | | `data.indicators.registration.privacy_protected` | boolean | | `data.indicators.registration.registrar` | string | | `data.indicators.registration.created_date` | string | | `data.indicators.infrastructure` | object | | `data.indicators.infrastructure.ip` | string | | `data.indicators.infrastructure.hosting` | string | | `data.indicators.infrastructure.geolocation` | string | | `data.indicators.ssl` | object | | `data.indicators.ssl.valid` | boolean | | `data.indicators.ssl.issuer` | string | | `data.indicators.ssl.age_days` | number | | `data.indicators.reputation` | object | | `data.indicators.reputation.blocklisted` | boolean | | `data.indicators.reputation.similar_reports` | number | | `data.comparison_to_legitimate` | object | | `data.comparison_to_legitimate.similarity_score` | number | | `data.comparison_to_legitimate.visual_differences[]` | string[] | | `data.evidence_package` | object | | `data.evidence_package.dns_snapshot` | object | | `data.evidence_package.dns_snapshot.A[]` | string[] | | `data.evidence_package.whois_snapshot` | object | | `data.evidence_package.whois_snapshot.registrar` | string | | `data.evidence_package.timestamp` | string | | `data.recommended_actions[]` | string[] | | `meta` | object | | `meta.recipe_name` | string | | `meta.credits_used` | number | | `meta.credits_saved` | number | | `meta.duration_ms` | number | | `meta.components_called[]` | string[] | | `meta.cached_components[]` | array | | `meta.timestamp` | string | | `errors[]` | array | #### Example request ```bash curl -H "X-API-Key: $DOMSCAN_API_KEY" "https://domscan.net/v1/recipes/phishing-investigation?suspicious_domain=examp1e.com&legitimate_domain=example.com&collect_evidence=true" ``` ```javascript const response = await fetch("https://domscan.net/v1/recipes/phishing-investigation?suspicious_domain=examp1e.com&legitimate_domain=example.com&collect_evidence=true", { headers: { "X-API-Key": process.env.DOMSCAN_API_KEY }, }); const data = await response.json(); console.log(data); ``` ```python import os import requests response = requests.get( "https://domscan.net/v1/recipes/phishing-investigation?suspicious_domain=examp1e.com&legitimate_domain=example.com&collect_evidence=true", headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]}, ) print(response.json()) ``` ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { req, err := http.NewRequest(http.MethodGet, "https://domscan.net/v1/recipes/phishing-investigation?suspicious_domain=examp1e.com&legitimate_domain=example.com&collect_evidence=true", nil) if err != nil { panic(err) } req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY")) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status, string(data)) } ``` ```ruby require "json" require "net/http" uri = URI("https://domscan.net/v1/recipes/phishing-investigation?suspicious_domain=examp1e.com&legitimate_domain=example.com&collect_evidence=true") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY") response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end puts JSON.pretty_generate(JSON.parse(response.body)) ``` #### Example response ```json { "success": true, "data": { "suspicious_domain": "examp1e.com", "legitimate_domain": "example.com", "verdict": "confirmed_phishing", "confidence": 0.93, "indicators": { "typosquatting": { "detected": true, "technique": "character_swap" }, "domain_age": { "days": 3, "risk": "high" }, "registration": { "privacy_protected": true, "registrar": "Example Registrar", "created_date": "2026-04-12" }, "infrastructure": { "ip": "203.0.113.18", "hosting": "Suspicious Hosting Ltd.", "geolocation": "NL" }, "ssl": { "valid": true, "issuer": "Let's Encrypt", "age_days": 2 }, "reputation": { "blocklisted": true, "similar_reports": 4 } }, "comparison_to_legitimate": { "similarity_score": 0.97, "visual_differences": [ "digit-substitution in second label character" ] }, "evidence_package": { "dns_snapshot": { "A": [ "203.0.113.18" ] }, "whois_snapshot": { "registrar": "Example Registrar" }, "timestamp": "2026-04-15T11:24:00Z" }, "recommended_actions": [ "Report to registrar abuse contact", "Submit URL to Safe Browsing and internal blocklists" ] }, "meta": { "recipe_name": "phishing-investigation", "credits_used": 12, "credits_saved": 10, "duration_ms": 952, "components_called": [ "whois", "dns", "ip", "reputation", "health", "certificates" ], "cached_components": [], "timestamp": "2026-04-15T11:24:00Z" }, "errors": [] } ``` #### HTTP status codes - `200` OK - `400` Bad Request - `401` Unauthorized - `402` Payment Required - `429` Too Many Requests ## Reference resources [OpenAPI 3.0](https://domscan.net/v1/openapi.json) [Postman](https://domscan.net/v1/postman.json) [MCP](https://domscan.net/mcp-domain-checker)