DomScan Web Intelligence API
Tech stack detection, categorization, and reputation
Tech stack detection, categorization, and reputation
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/domscan-web-intelligence-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: DomScan Web Intelligence API
description: DomScan is a domain intelligence API providing domain analysis tools.
version: 2.15.0
contact:
name: DomScan Support
url: https://domscan.net
email: support@domscan.net
termsOfService: https://domscan.net/legal/terms
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://domscan.net
description: Production server
security:
- apiKey: []
tags:
- name: Web Intelligence
description: Tech stack detection, categorization, and reputation
paths:
/v1/hosting/bulk:
post:
operationId: bulkGetHosting
summary: Detect infrastructure for multiple domains
description: Detect hosting, CDN, WAF, DNS, and email infrastructure for multiple domains. Accepts up to 10 items, preserves input order, and uses bounded concurrency. The outer response is HTTP 200 when the batch is accepted, so inspect each result for data or an error. Billing is 3 credits per validated item with no bulk discount, including items that return a per-item lookup error.
tags:
- Web Intelligence
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- domains
properties:
domains:
type: array
minItems: 1
maxItems: 10
items:
type: string
format: hostname
example:
domains:
- example.com
- cloudflare.com
responses:
'200':
description: Batch accepted. Each ordered result contains either data or a per-item error.
content:
application/json:
schema:
$ref: '#/components/schemas/BulkLookupResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'429':
$ref: '#/components/responses/RateLimited'
x-domscan-credits:
model: per_item
default: 3
/v1/tech:
get:
tags:
- Web Intelligence
summary: Detect tech stack
description: Identify technologies exposed by a public website. Fast mode inspects one bounded response, rendered mode loads one public page with JavaScript, and deep mode analyzes up to five same-origin pages. Results include stable IDs, confidence, sanitized page-scoped evidence, version semantics, provenance, caveats, and explicit coverage limits. url takes precedence when both aliases are supplied.
operationId: getTechStack
x-required-any-of:
- - url
- - domain
parameters:
- name: url
in: query
required: false
description: Full public HTTP(S) URL to analyze. Takes precedence over domain when both are supplied.
schema:
type: string
format: uri
minLength: 1
maxLength: 2048
- name: domain
in: query
required: false
description: Public domain or HTTP(S) URL to analyze. At least one of url or domain is required.
schema:
type: string
minLength: 1
maxLength: 2048
- name: mode
in: query
required: false
description: Scan profile. fast costs 3 credits, rendered costs 6, and deep costs 9.
schema:
type: string
enum:
- fast
- rendered
- deep
default: fast
- name: max_pages
in: query
required: false
description: Maximum same-origin rendered pages in deep mode. Other modes require 1.
schema:
type: integer
minimum: 1
maximum: 5
default: 3
- name: skip_cache
in: query
required: false
description: Set to 1 to bypass fresh and stale fast-scan caches.
schema:
type: string
enum:
- '0'
- '1'
default: '0'
responses:
'200':
description: Technology stack
content:
application/json:
schema:
$ref: '#/components/schemas/TechStackResponse'
examples:
completeWordPress:
summary: Complete HTML analysis with a verified WordPress detection
value:
url: https://wordpress.example/
technologies:
- id: wordpress
name: WordPress
category: cms
version: 6.8.2
version_kind: product
confidence: high
confidence_score: 98
evidence: 'Meta: generator'
evidence_details:
- source: meta
key: generator
matched: WordPress 6.8.2
source_count: 1
caveats:
- generator_can_be_removed_or_spoofed
- asset_paths_can_be_rewritten
reference:
website: https://wordpress.org/
source_url: https://developer.wordpress.org/reference/functions/get_the_generator/
source_owner: WordPress.org
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: medium
runtime_rate_limits: not_applicable_no_source_request
fallback_behavior: unmatched_or_unavailable_signal_is_not_detected
last_verified: '2026-07-15'
detection_summary:
detected_count: 1
category_count: 1
categories:
- cms
high_confidence_count: 1
medium_confidence_count: 0
low_confidence_count: 0
versioned_count: 1
evidence_sources:
header: 0
html: 0
asset_url: 0
network_url: 0
javascript: 0
meta: 1
cookie: 0
url: 0
catalog_size: 522
catalog_category_count: 87
summary_field_count: 1
summary:
cms: WordPress
meta:
title: Example WordPress site
description: A reserved example response for the technology detection contract.
canonical_url: https://wordpress.example/
language: en
favicon: https://wordpress.example/favicon.ico
open_graph:
title: null
description: null
image: null
url: null
type: null
site_name: null
locale: null
twitter_card:
card: null
site: null
creator: null
title: null
description: null
image: null
author: null
generator: WordPress 6.8.2
theme_color: null
manifest_url: null
robots: index, follow
headers:
content-type: text/html; charset=UTF-8
ssl:
enabled: true
analysis:
status: complete
requested_url: https://wordpress.example/
final_url: https://wordpress.example/
response_status: 200
redirect_count: 0
relay_used: false
signals_checked:
- url
- header
- cookie
- html
- asset_url
- meta
signals_unavailable: []
html_characters_analyzed: 412
html_bytes_analyzed: 412
html_byte_limit: 1000000
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: 0
page_limit_reached: false
resource_limit_reached: false
redirected_to_different_host: false
no_detection_reason: null
recommended_mode: null
pages:
- url: https://wordpress.example/
status: 200
html_truncated: false
network_requests_observed: 0
total_time_ms: 128
checked_at: '2026-07-15T10:30:00Z'
_meta:
served_by: pop=MAD country=ES
analysis_status: ok
response_status: 200
cache_status: miss
stale: false
completeNoDetections:
summary: Complete HTML analysis with no verified detections
value:
url: https://plain.example/
technologies: []
detection_summary:
detected_count: 0
category_count: 0
categories: []
high_confidence_count: 0
medium_confidence_count: 0
low_confidence_count: 0
versioned_count: 0
evidence_sources:
header: 0
html: 0
asset_url: 0
network_url: 0
javascript: 0
meta: 0
cookie: 0
url: 0
catalog_size: 522
catalog_category_count: 87
summary_field_count: 0
summary: {}
meta:
title: Plain example site
description: null
canonical_url: null
language: en
favicon: null
open_graph:
title: null
description: null
image: null
url: null
type: null
site_name: null
locale: null
twitter_card:
card: null
site: null
creator: null
title: null
description: null
image: null
author: null
generator: null
theme_color: null
manifest_url: null
robots: null
headers:
content-type: text/html; charset=UTF-8
ssl:
enabled: true
analysis:
status: complete
requested_url: https://plain.example/
final_url: https://plain.example/
response_status: 200
redirect_count: 0
relay_used: false
signals_checked:
- url
- header
- cookie
- html
- asset_url
- meta
signals_unavailable: []
html_characters_analyzed: 143
html_bytes_analyzed: 143
html_byte_limit: 1000000
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: 0
page_limit_reached: false
resource_limit_reached: false
redirected_to_different_host: false
no_detection_reason: no_verified_signature_fast_mode
recommended_mode: rendered
pages:
- url: https://plain.example/
status: 200
html_truncated: false
network_requests_observed: 0
total_time_ms: 91
checked_at: '2026-07-15T10:31:00Z'
_meta:
served_by: pop=MAD country=ES
analysis_status: ok
response_status: 200
cache_status: miss
stale: false
partialCloudflareHeaders:
summary: Partial analysis with a verified Cloudflare response-header detection
value:
url: https://protected.example/
technologies:
- id: cloudflare
name: Cloudflare
category: cdn
confidence: high
confidence_score: 96
evidence: 'Header: server'
evidence_details:
- source: header
key: server
matched: cloudflare
source_count: 1
caveats:
- response_headers_can_be_spoofed
reference:
website: https://www.cloudflare.com/
source_url: https://developers.cloudflare.com/fundamentals/reference/http-headers/
source_owner: Cloudflare
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: medium
runtime_rate_limits: not_applicable_no_source_request
fallback_behavior: unmatched_or_unavailable_signal_is_not_detected
last_verified: '2026-07-15'
detection_summary:
detected_count: 1
category_count: 1
categories:
- cdn
high_confidence_count: 1
medium_confidence_count: 0
low_confidence_count: 0
versioned_count: 0
evidence_sources:
header: 1
html: 0
asset_url: 0
network_url: 0
javascript: 0
meta: 0
cookie: 0
url: 0
catalog_size: 522
catalog_category_count: 87
summary_field_count: 1
summary:
cdn: Cloudflare
meta:
title: null
description: null
canonical_url: null
language: null
favicon: null
open_graph:
title: null
description: null
image: null
url: null
type: null
site_name: null
locale: null
twitter_card:
card: null
site: null
creator: null
title: null
description: null
image: null
author: null
generator: null
theme_color: null
manifest_url: null
robots: null
headers:
content-type: text/html; charset=UTF-8
cf-mitigated: challenge
server: cloudflare
ssl:
enabled: true
analysis:
status: partial
requested_url: https://protected.example/
final_url: https://protected.example/
response_status: 403
redirect_count: 0
relay_used: false
signals_checked:
- url
- header
- cookie
signals_unavailable:
- html
- asset_url
- meta
html_characters_analyzed: 0
html_bytes_analyzed: 0
html_byte_limit: 1000000
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: 0
page_limit_reached: false
resource_limit_reached: false
redirected_to_different_host: false
no_detection_reason: null
recommended_mode: null
pages:
- url: https://protected.example/
status: 403
html_truncated: false
network_requests_observed: 0
total_time_ms: 164
checked_at: '2026-07-15T10:32:00Z'
_meta:
served_by: pop=MAD country=ES
analysis_status: blocked
response_status: 403
cache_status: miss
stale: false
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/TechPaymentRequired'
'429':
$ref: '#/components/responses/RateLimited'
'503':
$ref: '#/components/responses/TechServiceUnavailable'
x-domscan-credits:
model: per_request
default: 3
variants:
- parameter: mode
equals: rendered
credits: 6
- parameter: mode
equals: deep
credits: 9
note: Fast scans cost 3 credits, one-page JavaScript-rendered scans cost 6, and deep scans of up to five same-origin pages cost 9.
/v1/scrape:
post:
tags:
- Web Intelligence
summary: Scrape one public web page
description: Retrieve one public HTTP(S) page with bounded redirects and response size. Standard uses one attempt, resilient permits one eligible retry, and rendered modes execute JavaScript in an isolated browser. Free accounts can use standard mode only, with 5 requests per minute, one concurrent request, 100 requests per day, 500 per month, and a 256 KiB response limit. Paid accounts allow 60 requests per minute, up to five concurrent standard or resilient requests, up to two concurrent rendered requests, and a 512 KiB response limit. CAPTCHA solving and premium proxy selection are not offered. Billing is based on processing effort, so target HTTP errors, blocks, rate limits, timeouts, and unsupported content remain charged. Invalid targets cost zero and verified DomScan platform failures are refunded.
operationId: scrapePage
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- url
additionalProperties: false
properties:
url:
type: string
format: uri
minLength: 1
maxLength: 2048
mode:
type: string
enum:
- standard
- resilient
- rendered
- rendered_resilient
default: standard
description: standard costs 1 credit, resilient costs 2, rendered costs 10, and rendered_resilient costs 20. Free accounts can use standard mode only.
output:
type: string
enum:
- html
- text
- markdown
default: html
example:
url: https://example.com/
mode: standard
output: markdown
responses:
'200':
description: Processed target result. A non-success outcome describes the target response and remains billable.
content:
application/json:
schema:
type: object
required:
- data
- billing
properties:
data:
$ref: '#/components/schemas/ScrapeResult'
billing:
$ref: '#/components/schemas/ScrapeBilling'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/RateLimited'
'503':
$ref: '#/components/responses/ServiceUnavailable'
x-domscan-credits:
model: per_item
default: 1
variants:
- parameter: mode
equals: resilient
credits: 2
- parameter: mode
equals: rendered
credits: 10
- parameter: mode
equals: rendered_resilient
credits: 20
note: Standard costs 1 credit, resilient costs 2, rendered costs 10, and rendered resilient costs 20. Billing is based on processing effort, not target-site success. Invalid targets cost zero and verified platform failures are refunded.
/v1/scrape/jobs:
post:
tags:
- Web Intelligence
summary: Create an asynchronous scrape job
description: Paid accounts can queue 1 to 100 public URLs, with up to three active jobs and 300 queued items per account. Job creation is limited to five requests per minute. Every accepted URL is charged at the selected mode price. Results are retained for 24 hours and job metadata for seven days. CAPTCHA solving and premium proxy selection are not offered. Target-site failures remain billed; items that cannot be processed because of a verified platform failure are refunded.
operationId: createScrapeJob
parameters:
- name: Idempotency-Key
in: header
required: true
description: Printable ASCII key, 1 to 128 characters. Reuse with identical input returns the original job.
schema:
type: string
minLength: 1
maxLength: 128
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- urls
additionalProperties: false
properties:
mode:
type: string
enum:
- standard
- resilient
- rendered
- rendered_resilient
default: standard
output:
type: string
enum:
- html
- text
- markdown
default: html
urls:
type: array
minItems: 1
maxItems: 100
uniqueItems: true
items:
oneOf:
- type: string
format: uri
maxLength: 2048
- type: object
required:
- url
additionalProperties: false
properties:
url:
type: string
format: uri
maxLength: 2048
reference:
type: string
minLength: 1
maxLength: 128
example:
mode: resilient
output: text
urls:
- https://example.com/
- url: https://example.org/
reference: page-2
responses:
'202':
description: Job accepted or idempotently replayed
content:
application/json:
schema:
type: object
properties:
job:
$ref: '#/components/schemas/ScrapeJob'
idempotent_replay:
type: boolean
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/RateLimited'
'503':
$ref: '#/components/responses/ServiceUnavailable'
x-domscan-credits:
model: per_item
default: 1
variants:
- parameter: mode
equals: resilient
credits: 2
- parameter: mode
equals: rendered
credits: 10
- parameter: mode
equals: rendered_resilient
credits: 20
note: Each accepted URL uses the selected mode price. Target-site failures remain billed; only verified platform failures are refunded.
/v1/scrape/jobs/{job_id}:
get:
tags:
- Web Intelligence
summary: Get asynchronous scrape job progress
operationId: getScrapeJob
parameters:
- name: job_id
in: path
required: true
schema:
type: string
pattern: ^scj_[a-f0-9]{32}$
responses:
'200':
description: Owner-scoped job status and billing settlement
content:
application/json:
schema:
type: object
properties:
job:
$ref: '#/components/schemas/ScrapeJob'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
x-domscan-credits:
model: per_request
default: 0
/v1/scrape/jobs/{job_id}/results:
get:
tags:
- Web Intelligence
summary: Get asynchronous scrape job results
operationId: getScrapeJobResults
parameters:
- name: job_id
in: path
required: true
schema:
type: string
pattern: ^scj_[a-f0-9]{32}$
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: Ordered page of item results
content:
application/json:
schema:
type: object
properties:
job:
$ref: '#/components/schemas/ScrapeJob'
results:
type: array
items:
type: object
properties:
index:
type: integer
url:
type: string
format: uri
reference:
type: string
status:
type: string
enum:
- pending
- processing
- succeeded
- failed
data:
$ref: '#/components/schemas/ScrapeResult'
billing:
$ref: '#/components/schemas/ScrapeBilling'
pagination:
type: object
additionalProperties: true
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'410':
$ref: '#/components/responses/Gone'
'429':
$ref: '#/components/responses/RateLimited'
x-domscan-credits:
model: per_request
default: 0
/v1/tech/bulk:
post:
tags:
- Web Intelligence
summary: Bulk detect technology stacks
description: Run the fast detector for up to 10 ordered targets. Invalid targets cost zero. Each attempted target costs 3 credits, including target HTTP errors, blocks, empty responses, and network failures. A verified DomScan service failure is refunded per item.
operationId: postTechStackBulk
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- targets
properties:
mode:
type: string
enum:
- fast
default: fast
targets:
type: array
minItems: 1
maxItems: 10
items:
$ref: '#/components/schemas/TechScanTarget'
example:
mode: fast
targets:
- example.com
- url: https://shop.example.com/
reference: crm-42
responses:
'200':
description: Ordered bulk technology results with item-level billing settlement
content:
applica
# --- truncated at 32 KB (144 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/domscan/refs/heads/main/openapi/domscan-web-intelligence-api-openapi.yml