Skip to main content

Subdomain enumeration

Usage​

This endpoint returns distinct subdomain names found in Profundis's indexed DNS observations. It does not perform live DNS resolution or prove that every returned name still exists. You can also use the web UI and download the loaded results as CSV, JSON or TXT.

The personal API requires a paid subscription or unused purchased credits. A Free account's monthly allocation alone does not grant API access. See API usage and Generate a token.

How do I send a request?​

Send a POST request to https://api.profundis.io/api/v2/common/data/subdomains. Replace the key and domain in this example:

API_KEY='YOUR_API_KEY'

curl "https://api.profundis.io/api/v2/common/data/subdomains" \
-H "X-API-KEY: $API_KEY" \
-H "Accept: text/event-stream" \
-H "Content-Type: application/json" \
-N \
-X POST \
-d '{
"domain": "example.com",
"max_credits": 3
}'
FieldMeaning
domainRequired domain name, such as example.com. You can use api.example.com to look for names beneath that subdomain. Do not include *., a URL scheme or a path.
max_creditsOptional integer spending limit for this request, from 1 to 100000. Omit it or set it to 0 for no request-specific limit; your available credits still apply.
sourceOptional label identifying the caller in request logs. It does not change billing or access.

Malformed JSON, unknown fields, an invalid domain or an out-of-range max_credits returns HTTP 400 before enumeration starts.

How much does it cost?​

The endpoint charges 1 credit per batch of up to 100 names for the first 300, then 1 credit per batch of up to 300 names beyond that. A final partial batch also costs 1 credit. A successful enumeration costs at least 1 credit, even when no names are found.

For example, 100 names cost 1 credit, 300 cost 3, and 600 cost 4. Charges happen before each batch is sent. See Credits.

The example's max_credits: 3 allows at most 3 credits to be charged. If more names remain, enumeration stops before charging the next batch. The ceiling is not a charge made in advance.

How do I read the response?​

A started enumeration returns HTTP 200 with Content-Type: text/event-stream; charset=utf-8. Its body is a newline-delimited stream, not a JSON array or standard SSE data: frames. Read it line by line with a streaming HTTP client; curl -N disables output buffering.

  • Plain text lines are subdomain names, in lowercase and without duplicates.
  • JSON lines with "type":"credits" report the account's credit state after charged batches and at stream end. They are control messages, not subdomains.
  • JSON lines with code and message, error or notice describe an error or limit. Keep them separate from the names you collect.

The credits object contains monthly_credits, credits_used, balance and cycle_end. A snapshot can be omitted if it cannot be loaded. When you set a positive max_credits, the final credits control line also reports credits_charged: the actual cost of this request. If that ceiling stops the list, it includes capped: true and max_credits.

For example, if more than 300 names are available and the ceiling of 3 credits stops enumeration, the final credits control line includes:

{
"type": "credits",
"credits_charged": 3,
"capped": true,
"max_credits": 3
}

The account's credits snapshot is omitted from this example for brevity. If the ceiling is not reached, capped and max_credits are absent. A credit error can follow the final credits line, so read the entire response.

Frequent questions​

The DNS search shows individual DNS observations, including different record types, values and dates for the same host. Enumeration returns each matching name only once, without its DNS values or history. A credit balance or request spending limit can also stop the list early. Neither view guarantees a complete live inventory.

Does the Free plan's 300-name limit apply to this API?​

The 300-name limit applies to web UI enumeration by a Free account without unused purchased credits. Personal API calls require the paid subscription or purchased balance described above; qualifying calls do not have that Free-plan cap. They remain bounded by available credits and any max_credits you set.

What happens when I run out of credits?​

There are two cases:

  • Before the stream starts: no spendable credits, or no qualifying API access, returns HTTP 402 with a JSON error containing code: "Q2014" and a human-readable message. Enumeration does not start and nothing is charged.
  • After the stream starts: if the next batch cannot be paid for, the response remains HTTP 200 and ends with a JSON error line containing code: "Q2014". Names already sent remain usable, and the batches already delivered remain charged. Treat the list as incomplete.

Use the status and code in your integration rather than matching the wording of message. Q2014 identifies a credit or API-access block, not a daily or monthly search-quota counter. Buy a credit pack or, for a paid subscription's exhausted allocation, wait for its next cycle. Renewing a Free monthly allocation does not restore API access without purchased credits or a paid subscription.

A self-set usage guard can also stop a charge even when credits remain. Its error code is Q2015; wait for the guard's window to reset or adjust the limit in your profile. This is separate from the per-request max_credits ceiling, which is reported by capped: true rather than a credit error.