# Typosquatting Check – Lookalike Domains That Resolve in DNS (`pontio/domain-lookalike-check`) Actor

See which typo versions of your domain resolve in DNS: up to 30 lookalike variants per domain, each with its A/AAAA evidence. DNS evidence only, no registration, availability or phishing verdict. Incomplete scans are uncharged.

- **URL**: https://apify.com/pontio/domain-lookalike-check.md
- **Developed by:** [Gabor Molnar](https://apify.com/pontio) (community)
- **Categories:** Developer tools, SEO tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 bounded typo dns scans

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Typosquatting Check – Lookalike Domains That Resolve in DNS

Give it your domain and it generates up to 30 typo versions of it (a dropped letter, two letters swapped, a neighbouring key) and tells you which ones resolve in DNS. A typo domain that resolves is worth a look; on its own it is not proof of typosquatting (see below). Each run is a snapshot; put it on an Apify schedule to repeat it.

### Use it when

- You want to know which misspellings of your brand's domain are live before a customer lands on one.
- You run brand-protection or phishing-exposure checks for clients and need the DNS evidence as rows, not a screenshot.
- An agent needs a bounded, repeatable list of lookalike candidates with resolution status.

### How it works

A supplied registrable ASCII domain → deterministic typo variants and observed A/AAAA DNS evidence via Cloudflare's public DNS resolver. Snapshot only: nothing is remembered between runs.

```json
{ "domains": ["example.com"] }
```

Up to **5 raw seeds/run**, **30 variants/seed**, **60 sequential DNS queries/seed**. Each query has a 5-second deadline including response parsing, long enough for the resolver to give up on a lame delegation (about 4 seconds); a query that misses it is asked once more, and other failures are not retried. A **150-second total budget per seed** covers all attempts, retries and parsing; the final attempt is shortened to the remaining budget. On exhaustion, remaining generated A/AAAA evidence is `unknown` without more network calls, and the seed persists free as `partial` or `upstream_error`. Seeds remain sequential against the shared resolver: five seeds have at most 750 seconds of DNS waiting, leaving startup/persistence margin within the existing 960-second default run timeout. No seed-domain query. Candidate order: single-character deletion, adjacent transposition, then left/right neighbours in the QWERTY letter rows `qwertyuiop`, `asdfghjkl`, `zxcvbnm`. Deduplication and cap happen before querying. Only the registrable label changes; the ICANN suffix stays unchanged. No insertions, suffix swaps, homographs or IDN generation. `truncated` reports capped candidates; each query caps observed addresses at 16 and separately reports truncation.

Accepted seed spellings normalize case, whitespace, URL/email form, port, trailing dot and `www.` prefix. Normalized repeats yield one row and at most one charge; distinct invalid junk stays distinct. Other subdomains, unknown/non-ICANN suffixes, nonregistrable names and normalized `xn--` labels are refused. Normalization does not discover a company's domain.

Rows contain normalized `domain` (null if invalid), `variants` with separate `a`/`aaaa` statuses and addresses, query counts, elapsed time and limits. `NOERROR` and `NXDOMAIN` are resolver answers. `SERVFAIL` is recorded only when the resolver reports the name is delegated but no authoritative nameserver answers (a lame delegation, common for parked or abandoned typo registrations); other SERVFAILs are `unknown`. `unknown` means a DNS/HTTP/transport/payload failure or exhausted seed budget. `queries` counts logical queries actually attempted, excluding retries and budget-skipped queries; `answeredQueries` counts conclusive evidence and `unknownQueries` counts all unresolved generated evidence, including skipped queries. Thus `answeredQueries + unknownQueries = 2 × variants.length`, while `queries` can be smaller. Any unknown makes the entire seed free, with answered evidence retained. A fully answered **capped** scan is an answer even when none of its variants yields addresses. A one-character digit label can produce no valid candidates; that completed empty generation also bills, with zero queries explicitly reported.

**DNS resolution is not registration, purchase availability, ownership, maliciousness or phishing.** A DNS-negative response does not prove a name is unregistered or safe. An address may be parking, wildcard DNS, shared hosting or unrelated content. No RDAP or website fetches, threat scores or exhaustive coverage claims.

### Billing

**$0.01 per completed seed**, not per variant or address. A charge cap stops the batch early; unprocessed seeds have no dataset row or charge. The `truncated` flags describe candidate/address caps, not omitted seeds.

| reasonCode | Meaning | Charged? |
|---|---|---|
| `checked` | Every generated, capped A/AAAA query answered, including empty address results | yes |
| `invalid_domain` | Unsupported or unusable seed; no DNS query | no |
| `partial` | Some queries answered, some unknown; retained evidence is incomplete | no |
| `upstream_error` | No generated queries answered | no |

### Source and access

[Cloudflare's free public resolver](https://developers.cloudflare.com/1.1.1.1/) documents the [unauthenticated JSON DoH endpoint](https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/). Its [resolver terms](https://developers.cloudflare.com/1.1.1.1/terms-of-use/) incorporate [Website and Online Services Terms](https://www.cloudflare.com/website-terms/), including no overload or limit circumvention. Documented public API use is not blanket rights over third-party content or trademarks. Only DNS evidence is collected here; callers remain responsible for lawful use. Service availability and data accuracy are not guaranteed by Cloudflare.

# Changelog

This Actor's version history is a separate document: https://apify.com/pontio/domain-lookalike-check/changelog.md

# Actor input Schema

## `domains` (type: `array`):

Up to 5 registrable ASCII seeds with ICANN suffixes; subdomains other than normalized www, unknown suffixes and IDN/punycode seeds are refused. Case, whitespace, URL/email form, port and trailing dot normalize; repeats once, distinct junk separately. At most 30 typo variants and 60 sequential DNS queries per seed, within a total 150-second seed budget including retries and parsing; remaining evidence is unknown and free. DNS evidence only, not registration, availability, ownership or phishing detection.

## Actor input object example

```json
{
  "domains": [
    "a.com"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

Results produced by this run, in its default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "a.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pontio/domain-lookalike-check").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": ["a.com"] }

# Run the Actor and wait for it to finish
run = client.actor("pontio/domain-lookalike-check").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "a.com"
  ]
}' |
apify call pontio/domain-lookalike-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pontio/domain-lookalike-check"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9cAqfsB9j5yuvTtxm/builds/VfGNyyXVia1fkQH6p/openapi.json
