Skip to main content
A scan takes one domain your organization owns, such as acme.com, and finds its registered look-alikes. It generates candidate names, searches new domain registrations and certificate transparency logs, and looks up the DNS records of every candidate. Each candidate with name servers becomes a result. Results with a live web server then get a screenshot, a URL risk score and, when you attach them, brand keyword and logo checks. The flow is asynchronous: start the scan, poll it while it runs, then read, filter and triage its results. The API calls a scan an analysis. Monitor look-alike domains explains how scans fit with the brand library, look-alike alerts and takedowns. Availability: Domain Monitoring. Plans and quotas lists what each plan includes. Cost: no metered allowance. Starting a scan of a new domain takes one Monitored Assets slot, held until you delete the scan. Monitors draw on the same slots. Rescans, polling, results, triage and exports take no slot. Calls made with your API key count toward the API Calls allowance and the per-second rate limit described in Rate limits. Only 2xx responses count toward the allowance. Every endpoint on this page returns 403 with {"detail": "This feature is not included in your plan."} when your plan lacks Domain Monitoring, and also when your license is not in force. start_domain_analysis also returns 409 when every Monitored Assets slot is in use:
No endpoint on this page has a metered allowance, so none returns the allowance 429 with resource and period. Monitored Assets slots explains how to free a slot.

Before you start

Register the domain as an asset of your organization. Call organization_assets_create with asset_type set to domain and the domain in value, or add it in the dashboard under Manage → Assets. Registering an asset needs a license in force.
A subdomain such as shop.acme.com must be registered as its own asset before you can scan it. When its parent domain is already registered, organization_assets_create registers nothing and answers 200 with "detail": "Asset is covered by an existing broader asset; nothing was created.". A logo, brand keywords, a word list and trusted domains make a scan check more. Create them in the brand library before you start, or attach them later. See Set up a brand library.

Start a scan

start_domain_analysis needs one field, domain.
The call returns 200 with the new scan’s ID:
Keep analysis_id. Every other call on this page takes it. params echoes the settings the scan runs with, and params.modules lists every detection module it runs. An entry for a module that is no longer offered can have module_name set to null. The list is shortened here. The value of domain is cleaned before it is matched against your registered assets. A scheme, path, port, user name and trailing dot are removed, the name is lowercased, and an internationalized name is converted to its xn-- form. https://ACME.com/login is read as acme.com.
The scan picks its own detection modules. A modules list in the body is ignored, and the call still succeeds. analysis_configs lists the modules, the look-alike alert conditions and the default word lists, for reference.

Optional fields

Two of these fields add a module to the scan. The IDs come from your organization’s brand library.
Without a logo or keywords, the scan still runs. module_statuses in the scan says which checks did not run.

Start a domain you already scan

Each domain has one scan. Starting it again does not create a second one:
  • The scan has finished or was stopped. The call returns 200 with the existing analysis_id, its total_count, and a status_message saying the scan is reused. Nothing reruns, and the fields you sent are not applied. To change the settings, update the scan, then rescan it.
  • The scan is still running or initial_completed. The call returns 400 with the scan’s ID:

Why a start is refused

The checks run in this order. The first one that fails answers:
  1. Plan feature. 403, as above.
  2. Rate limit. 429 with "message": "Rate limit exceeded" when you hit the per-second rate limit or your API Calls allowance. See Rate limits.
  3. Monitored Assets slots. 409. At the limit, every start is refused, even one for a domain you already scan. Use analysis_rescan for a domain you already scan.
  4. Registered asset. 400 when the domain is not a registered asset:
    A domain that cannot be read as a domain name at all, such as a number or an invalid internationalized name, returns {"domain": ["Invalid value."]}.
  5. Scanning service limit. 429 when your organization has sent 10 start requests in the past hour, counting starts from the dashboard. The message gives the wait in seconds.
  6. Scanning service checks. 400 with details when the scanning service does not accept your registered asset as a domain, when the domain is one of the 100 most visited domains on the internet, or when it already has a running scan. Also when 10 or more of your scans started within the last hour are still running, when an attachment ID is not in your brand library, or when you send more than 200 custom domains.
Errors quotes each message.

Follow progress

Poll analysis_detail with the analysis_id. Send page_size=1 while you poll, so each response carries one result. A poll every 30 seconds or slower is enough.
The response is shortened here. A scan moves through these states: Results are readable in every state, and counters grow while the scan runs. The response also carries the first page of results, with page, page_size, total_items and total_pages.

Read the scan

The same call returns the scan’s summary and one page of results.

The summary

module_statuses names each check that was skipped because nothing was attached:
An empty object means both checks ran.

Results

Each entry in results is one registered look-alike. This one is shortened:

Filter and sort results

Add filters as query parameters. Boolean filters take true or false, and apply only when you send them. Without a sort, results come in the order they were found.
urlscore sorts. It does not filter. urlscore=desc returns every result, highest score first. urlscore=N/A returns no results at all.
This call lists the open look-alikes with a web server whose spoofing checks matched:

Count results by age and category

analysis_category_stats counts a scan’s results per domain-age bucket and category, in one call. Use it to size a triage queue before you page through the results.
The response is a list with one entry per bucket, always in this order: zero_to_one_week (under 7 days), one_week_to_month (7 to 29 days), month_to_six_months (30 to 179 days), older_than_six_months and age_unknown (no registration date).
The response is trimmed here to the first bucket. domains_per_category always carries the six standard categories, plus each custom category defined for your organization, even at 0. Custom categories are the ones you assign with analysis_assign_categories. A result with several categories counts once in each. The counts cover every result of the scan, including those your trusted domains hide, so they can exceed what the filtered results list shows.

Triage results

Mark a result reviewed once you have looked at it, with analysis_result_update and the result’s id:
The call returns 200 with an empty body. Send open to undo it. Then filter with status=open to see only what is left. You can set only open and reviewed. Three more statuses are set for you: Disabling or deleting that look-alike monitor, or deleting a takedown, sets the result back to reviewed. A reviewed status is not always a manual triage decision.
A rescan replaces every result, so it also discards their triage statuses.

Change a scan’s settings

PATCH analysis_detail changes only the fields you send. A null ID returns 400. An empty list is ignored. No field detaches an attachment. An empty body returns 400.
Monitor toggles are saved before the IDs are checked. A 400 for an unknown logo_id, branding_id or whitelist_id can still leave a monitor change in place. Send toggles and attachments in separate calls.
The call returns the updated scan. Trusted domains hide matching results at once. To check the whole scan against a new logo, keyword set or custom domain list, rescan it. To change the word list, send wordlist_code with the rescan.

Stop, rescan or delete

A rescan takes an optional wordlist_code. Without it, the scan keeps the word list it had.
The rescan returns 200 with analysis_id, total_count, params and the new candidates grouped by module in variations. Then follow its progress as for a new scan. A rescan that would generate more than 100,000 candidates is refused with 400, and the scan keeps its results. The refused word list stays saved on the scan. Send a different, shorter wordlist_code with the next rescan.

List scans and statistics

analysis_list returns your organization’s scans, including those started in the dashboard. They come newest first.
  • page starts at 1. page_size defaults to 10, and the most it returns is 100.
  • domain matches part of the scanned domain. status takes one of the four scan states.
  • Each entry has domain, status, uid, created_at, updated_at, params, total_variations and total_initial_done. uid is the analysis_id.
  • Raise page until next is null. A page past the last one returns 404.
Omit date_sort to list the newest first. date_sort=desc lists the oldest first, and date_sort=asc the newest first. A rescan resets created_at, so a rescanned domain moves to the top.
analysis_stats sums up the last 30 days across all your scans. It takes no parameters.
  • total_alerts_count, total_new_similar_domain_count, total_new_webservers_count, total_spoofed_count, total_high_risk_domains_count and total_phishing_count count look-alike alerts by kind.
  • daily_stats has one entry per day, each with a date and a data object: candidates generated, results found, web servers found, new name server records, new similar domains, look-alike monitors created, takedown requests other than drafts, the average URL score, and that day’s alerts.

Export a scan

Both exports return a CSV file. The file name comes in the Content-Disposition header.
The results export holds every result of the scan, including those your trusted domains hide. Its Module Name column holds the module code, and its Spoofing column is the brand keyword check. The candidates export lists every generated name, registered or not.

Errors

Most API refusals use detail, and most scanning-service refusals use details. Rate-limit 429s use message. The scanning service’s own 429 and its Invalid page. 404 use detail. Field errors are keyed by field name. Read the first of detail, details and message that the body contains. Monitor look-alike domains explains the shapes, and Handle API errors lists every body.

Endpoints