# URL Canonicalize API
> Normalize URLs to a canonical form so you can deduplicate, compare and clean them. The canonicalize endpoint lower-cases the scheme and host, drops the default port (80 for http, 443 for https), resolves ./ and ../ path segments and fixes percent-encoding using the standard WHATWG URL parser, then applies the cleanups you choose: strip marketing and analytics tracking parameters (all utm_* plus gclid, fbclid, msclkid, yclid, mc_eid and many more), sort the remaining query parameters into a stable order, optionally drop the #fragment, and add or remove the trailing slash. It returns the canonical URL, the fully parsed components and the exact list of changes it made. The compare endpoint canonicalizes two URLs and tells you whether they point to the same resource — perfect for catching duplicate links that differ only by tracking codes, casing, port or parameter order. Everything is computed locally with no network calls, so it is instant, private and safe. Ideal for crawlers and SEO tooling, link deduplication and analytics, cache keys, bookmarking and content pipelines. Pure local computation — no key, no third-party service, instant. Live, nothing stored. 3 endpoints. This canonicalizes the URL string; it does not fetch it or follow redirects — for link previews and unshortening use a URL-unfurl API.

## Authentication
All requests require your oanor API key in the `x-oanor-key` header. Get one at https://www.oanor.com/developer/keys.

```bash
curl -H "x-oanor-key: oanor_live_…" "https://api.oanor.com/urlcanon-api/..."
```

## Pricing
- **Free** (Free) — 4,035 calls/Mo, 2 req/s
- **Starter** ($6/Mo) — 13,550 calls/Mo, 8 req/s
- **Pro** ($25/Mo) — 186,500 calls/Mo, 20 req/s
- **Mega** ($63/Mo) — 975,000 calls/Mo, 50 req/s

## Endpoints

### URL

#### `GET /v1/canonicalize` — Canonicalize a URL

**Parameters:**
- `url` (query, required, string) — The URL (with scheme) Example: `HTTPS://Example.COM:443/a/./b/../c?utm_source=x&b=2&a=1`
- `remove_tracking` (query, optional, string) — Strip utm_*/gclid/fbclid… (default true)
- `sort_query` (query, optional, string) — Sort query parameters (default true)
- `remove_fragment` (query, optional, string) — Drop the #fragment (default false)
- `trailing_slash` (query, optional, string) — keep (default), add or remove
- `lowercase_path` (query, optional, string) — Lower-case the path (default false)

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/urlcanon-api/v1/canonicalize?url=HTTPS%3A%2F%2FExample.COM%3A443%2Fa%2F.%2Fb%2F..%2Fc%3Futm_source%3Dx%26b%3D2%26a%3D1"
```

**Response:**
```json
{
    "data": {
        "input": "HTTPS://Example.COM:443/a/./b/../c?utm_source=x&b=2&a=1",
        "changed": true,
        "changes": [
            "normalized scheme/host/port/path encoding",
            "removed tracking parameters",
            "sorted query parameters"
        ],
        "canonical": "https://example.com/a/c?a=1&b=2",
        "components": {
            "host": "example.com",
            "path": "/a/c",
            "port": null,
            "query": {
                "a": "1",
                "b": "2"
            },
            "scheme": "https",
            "fragment": null
        }
    },
    "meta": {
        "timestamp": "2026-06-03T09:24:58.352Z",
        "request_id": "a9b44bee-b3c4-40fc-a762-abe2e7b6abdd"
    },
    "status": "ok",
    "message": "Canonicalize a URL",
    "success": true
}
```

#### `GET /v1/compare` — Compare two URLs

**Parameters:**
- `a` (query, required, string) — First URL Example: `https://X.com/p?utm_source=z&a=1`
- `b` (query, required, string) — Second URL Example: `https://x.com:443/p?a=1`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/urlcanon-api/v1/compare?a=https%3A%2F%2FX.com%2Fp%3Futm_source%3Dz%26a%3D1&b=https%3A%2F%2Fx.com%3A443%2Fp%3Fa%3D1"
```

**Response:**
```json
{
    "data": {
        "a": {
            "input": "https://X.com/p?utm_source=z&a=1",
            "canonical": "https://x.com/p?a=1"
        },
        "b": {
            "input": "https://x.com:443/p?a=1",
            "canonical": "https://x.com/p?a=1"
        },
        "same": true
    },
    "meta": {
        "timestamp": "2026-06-03T09:24:58.453Z",
        "request_id": "3c540c9b-600e-4986-ad0f-19bab0a2a9a1"
    },
    "status": "ok",
    "message": "Compare two URLs",
    "success": true
}
```

### Meta

#### `GET /v1/meta` — Spec

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/urlcanon-api/v1/meta"
```

**Response:**
```json
{
    "data": {
        "name": "URL Canonicalize API",
        "notes": "Scheme and host are lower-cased and the default port dropped; the path is case-sensitive so it is left as-is unless lowercase_path is set. This canonicalizes the URL string locally — it does not fetch it or follow redirects (use a URL-unfurl/unshorten API for that). Nothing is stored.",
        "version": "v1",
        "endpoints": [
            {
                "path": "/v1/canonicalize",
                "params": {
                    "url": "the URL (required, with scheme)",
                    "sort_query": "sort query parameters (default true)",
                    "lowercase_path": "lower-case the path (default false)",
                    "trailing_slash": "keep (default), add or remove",
                    "remove_fragment": "drop the #fragment (default false)",
                    "remove_tracking": "strip utm_*/gclid/fbclid… (default true)"
                },
                "returns": "the canonical URL, its components and the changes made"
            },
            {
                "path": "/v1/compare",
                "params": {
                    "a": "first URL (required)",
                    "b": "second URL (required)",
                    "…options": "same options as canonicalize"
                },
                "returns": "whether a and b are the same URL, with both canonical forms"
            },
            {
                "path": "/v1/meta",
                "para
…(truncated, see openapi.json for full schema)
```


---
Marketplace page: https://www.oanor.com/api/urlcanon-api
OpenAPI spec: https://www.oanor.com/api/urlcanon-api/openapi.json
