# Duo Data Utilities – URL Parser & Registrable Domain Extractor

> Duo Data Utilities – URL Parser & Registrable Domain Extractor is a paid API for AI agents from api.duoleads.com, paid per call via x402, $0.05/call, status unknown (last checked 2026-10-02).

Parses and canonicalises a URL, extracting scheme, host, port, path, query parameters, fragment, public suffix, registrable domain (eTLD+1), and subdomain using the Public Suffix List.

## Facts

- Endpoint: GET https://api.duoleads.com/v1/code/url?utm_source=zero.xyz
- Price: $0.05/call
- Payment: x402
- Status: unknown
- Last checked: 2026-10-02
- Activations on Zero: 0
- Tags: x402
- Canonical page: https://www.zero.xyz/c/duo-data-utilities-url-parser-registrable-domain-extractor-8c90b1a5
- Structured record (JSON): https://api.zero.xyz/v1/capabilities/cap_bn49EHrBRF2OrJhXRF024

Status and success rate cover calls made through Zero and Zero's own probes. Third-party monitors may report differently.

## How to call it through Zero

Zero handles the 402 payment challenge and records the run. With the Zero CLI installed (`npm i -g @zeroxyz/cli`):

```sh
zero fetch --capability duo-data-utilities-url-parser-registrable-domain-extractor-8c90b1a5
```

Example prompt: Can you parse the URL 'https://a.b.example.co.uk/y?q=1&q=2#f' and tell me its registrable domain, subdomain, public suffix, and canonical form?

## When to prefer this

Choose this endpoint when you need accurate eTLD+1 extraction using the canonical Public Suffix List (including private suffixes like github.io), strict WHATWG-compliant URL parsing, or canonical URL normalisation. Prefer it over naive string splitting when dealing with multi-label TLDs (co.uk, com.au) or private registry suffixes where simple last-two-label heuristics fail.

## Known failure modes

- Missing or empty 'url' query parameter returns a validation error
- Malformed URL that cannot be parsed returns an error response
- Relative URL provided without a 'base' parameter may fail to resolve
- Unknown or unlisted TLD may result in null public_suffix/registrable_domain
- Payment failure (x402) blocks the request if USDC balance is insufficient
- URLs exceeding 2048 characters are rejected by the schema

## How this service works

Parse and canonicalise a URL, and extract its registrable domain using the Public Suffix List — the part an agent needs to decide whether two URLs belong to the same owner. Returns scheme, host, port, path, decoded query parameters and fragment, the public suffix, the registrable domain (eTLD+1), the subdomain, whether the suffix is an ICANN or a private entry, plus a canonical form with default port, dot-segments and percent-encoding normalised. unicode_host uses WHATWG/UTS 46 (non-strict).

## Output

Returns a JSON object with: scheme, host, port (null if default), path, decoded query parameter array (key/value pairs supporting repeated keys), fragment, username, host_type, unicode_host, public_suffix, suffix_source (icann or private), registrable_domain (eTLD+1), subdomain, and a canonical URL string with default ports stripped, dot-segments resolved, and percent-encoding normalised. Also includes metadata: PSL version/commit, price, request ID, and computed_at timestamp.

## Request schema (JSON Schema)

```json
{
 "type": "object",
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "required": [
  "input"
 ],
 "properties": {
  "input": {
   "type": "object",
   "required": [
    "type",
    "method"
   ],
   "properties": {
    "type": {
     "type": "string",
     "const": "http"
    },
    "method": {
     "enum": [
      "GET"
     ],
     "type": "string"
    },
    "queryParams": {
     "type": "object",
     "required": [
      "url"
     ],
     "properties": {
      "url": {
       "type": "string",
       "maxLength": 2048,
       "description": "Absolute URL, or a bare hostname (https:// assumed)."
      },
      "base": {
       "type": "string",
       "maxLength": 2048,
       "description": "Base URL to resolve url against as a relative reference."
      }
     }
    }
   },
   "additionalProperties": false
  },
  "output": {
   "type": "object",
   "required": [
    "type"
   ],
   "properties": {
    "type": {
     "type": "string"
    },
    "example": {
     "type": "object",
     "required": [
      "ok",
      "route",
      "version",
      "data",
      "meta"
     ],
     "properties": {
      "ok": {
       "const": true
      },
      "data": {
       "type": "object",
       "required": [
        "canonical",
        "scheme",
        "username",
        "host",
        "port",
        "path",
        "fragment",
        "query",
        "public_suffix",
        "registrable_domain",
        "subdomain",
        "suffix_source",
        "host_type",
        "unicode_host"
       ],
       "properties": {
        "host": {
         "type": [
          "string",
          "null"
         ]
        },
        "path": {
         "type": "string"
        },
        "port": {
         "type": [
          "string",
          "null"
         ]
        },
        "query": {
         "type": "array",
         "items": {
          "type": "object",
          "required": [
           "key",
           "value"
          ],
          "properties": {
           "key": {
            "type": "string"
           },
           "value": {
            "type": "string"
           }
          }
         }
        },
        "scheme": {
         "type": "string"
        },
        "fragment": {
         "type": [
          "string",
          "null"
         ]
        },
        "username": {
         "type": [
          "string",
          "null"
         ]
        },
        "canonical": {
         "type": "string"
        },
        "host_type": {
… (truncated)
```

## Response schema (JSON Schema)

```json
{
 "type": "json",
 "example": {
  "ok": true,
  "data": {
   "host": "a.b.example.co.uk",
   "path": "/y",
   "port": null,
   "query": [
    {
     "key": "q",
     "value": "1"
    },
    {
     "key": "q",
     "value": "2"
    }
   ],
   "scheme": "https",
   "fragment": "f",
   "username": null,
   "canonical": "https://a.b.example.co.uk/y?q=1&q=2#f",
   "host_type": "domain",
   "subdomain": "a.b",
   "unicode_host": null,
   "public_suffix": "co.uk",
   "suffix_source": "icann",
   "registrable_domain": "example.co.uk"
  },
  "meta": {
   "sources": [
    {
     "id": "public-suffix-list",
     "licence": "MPL-2.0",
     "version": "a179a48c465e818cfd8d626691cb317985da87fb",
     "published": "2026-09-24"
    }
   ],
   "price_usd": "0.05",
   "disclaimer": "Factual output of a deterministic computation over public data. Provided as is, with no warranty of accuracy, completeness or availability. Not investment, financial, legal, tax, medical or any other professional advice, and not a recommendation. Verify before relying on it. Terms: https://api.duoleads.com/terms",
   "request_id": "01K6B7Q4ZC8H3F2M9WXR5TYN0D",
   "computed_at": "2026-09-28T12:00:00.000Z",
   "deterministic": true
  },
  "route": "/v1/code/url",
  "version": "1.0.0"
 }
}
```

## More

- Live health (JSON, refreshed every minute): https://www.zero.xyz/c/duo-data-utilities-url-parser-registrable-domain-extractor-8c90b1a5/health.json
- [Zero catalog index](https://www.zero.xyz/llms.txt)
- [Other services from api.duoleads.com](https://www.zero.xyz/host/api.duoleads.com/llms.txt)
