> For the complete documentation index see https://domscan.net/llms.txt. Markdown versions of every docs page are available by appending .md to the page URL.

Source: https://domscan.net/docs/typosquatting

# Typosquatting Detection

DomScan API: Detect typosquatting threats and similar domains that could be used for phishing or brand abuse.

Detect typosquatting threats and similar domains that could be used for phishing or brand abuse.

GET /v1/typos

#### Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| domain required | string | Domain to check for typosquatting variants |
| limit optional | number | Max permutations to check (default: 50) |
| check_registered optional | boolean token Allowed values `1`, `true` Default `false` | Checks which permutations are already registered, up to 50 domains. Off by default because it adds upstream lookups. |

#### Example response

```json
{
                "domain": "google.com",
                "permutations_generated": 50,
                "registered_typos": [
                {
                "domain": "gooogle.com",
                "type": "repetition",
                "risk": "high",
                "registered": true
                },
                {
                "domain": "googIe.com",
                "type": "homoglyph",
                "risk": "critical",
                "registered": true
                }
                ],
                "threat_level": "critical",
                "risk_summary": {
                "critical": 2,
                "high": 5,
                "medium": 10,
                "low": 8
                }
                }
```

#### 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 |

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 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 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

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"))

```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")

#### 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

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
