tag string required A whitespace-free BCP 47 language tag, grandfathered tag or private-use-only tag.
Canonicalize BCP 47 language tags and run RFC 4647 lookup or basic filtering with bounded, deterministic matching.
Authoritative reference data or standards computation
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
tag
required
| string | allowed: 1 – 255 example: zh-hant-cn-u-ca-chinese-x-team | A whitespace-free BCP 47 language tag, grandfathered tag or private-use-only tag. |
tag string required A whitespace-free BCP 47 language tag, grandfathered tag or private-use-only tag.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: input,canonical | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: privateUse | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
input | string | Tag exactly as supplied. | EN-us |
canonical | string | Canonical casing, ordering and preferred replacement where supported. | en-US |
isCanonical | boolean | Whether input already exactly equals canonical output. | false |
kind | string | language-tag, grandfathered or private-use. | language-tag |
baseName nullable | string | Tag without extensions/private use, or null when that decomposition is not defined. | zh-Hant-CN |
language nullable | string | Canonical primary language subtag, or null for opaque forms. | zh |
script nullable | string | Four-letter script subtag when present. | Hant |
region nullable | string | Two-letter or three-digit region subtag when present. | CN |
extensions | string[] | Canonical singleton extension sequences excluding private use. | ["u-ca-chinese"] |
privateUse nullable | string | Complete x- private-use sequence when present. | x-team |
input string Tag exactly as supplied.
example: EN-us
canonical string Canonical casing, ordering and preferred replacement where supported.
example: en-US
isCanonical boolean Whether input already exactly equals canonical output.
example: false
kind string language-tag, grandfathered or private-use.
example: language-tag
baseName string nullable Tag without extensions/private use, or null when that decomposition is not defined.
example: zh-Hant-CN
language string nullable Canonical primary language subtag, or null for opaque forms.
example: zh
script string nullable Four-letter script subtag when present.
example: Hant
region string nullable Two-letter or three-digit region subtag when present.
example: CN
extensions string[] Canonical singleton extension sequences excluding private use.
example: ["u-ca-chinese"]
privateUse string nullable Complete x- private-use sequence when present.
example: x-team
/api/language-tags/canonicalize?tag=zh-hant-cn-u-ca-chinese-x-team {
"data": {
"input": "zh-hant-cn-u-ca-chinese-x-team",
"canonical": "zh-Hant-CN-u-ca-chinese-x-team",
"isCanonical": false,
"kind": "language-tag",
"baseName": "zh-Hant-CN",
"language": "zh",
"script": "Hant",
"region": "CN",
"extensions": [
"u-ca-chinese"
],
"privateUse": "x-team"
},
"meta": {
"endpoint": "language-tags",
"route": "/canonicalize",
"params": {
"tag": "zh-Hant-CN-u-ca-chinese-x-team"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/language-tags/canonicalize?tag=i-klingon {
"data": {
"input": "i-klingon",
"canonical": "tlh",
"isCanonical": false,
"kind": "grandfathered",
"baseName": "tlh",
"language": "tlh",
"script": null,
"region": null,
"extensions": [],
"privateUse": null
},
"meta": {
"endpoint": "language-tags",
"route": "/canonicalize",
"params": {
"tag": "tlh"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/language-tags/canonicalize?tag=X-TEAM-Internal {
"data": {
"input": "X-TEAM-Internal",
"canonical": "x-team-internal",
"isCanonical": false,
"kind": "private-use",
"baseName": null,
"language": null,
"script": null,
"region": null,
"extensions": [],
"privateUse": "x-team-internal"
},
"meta": {
"endpoint": "language-tags",
"route": "/canonicalize",
"params": {
"tag": "x-team-internal"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} | Parameter | Type | Default & allowed | Description |
|---|---|---|---|
ranges
required
| list | example: zh-Hant-TW,zh-Hant,zh | Priority-ordered basic language ranges; at most 20. '*' is skipped during lookup. |
available
required
| list | example: en,zh,zh-Hant | Available BCP 47 tags to canonicalize and search; at most 100. |
default | string | allowed: 1 – 255 example: en | Optional canonicalizable tag returned only if every priority range fails. |
ranges list required Priority-ordered basic language ranges; at most 20. '*' is skipped during lookup.
available list required Available BCP 47 tags to canonicalize and search; at most 100.
default string Optional canonicalizable tag returned only if every priority range fails.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: ranges,available | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: usedDefault | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
ranges | string[] | Validated lowercase priority ranges. | ["zh-hant-tw","zh-hant","zh"] |
available | string[] | Canonical, de-duplicated available tags. | ["en","zh","zh-Hant"] |
match nullable | string | Selected available tag, explicit default, or null. | zh-Hant |
matchedRange nullable | string | Normalized lowercase input priority range that succeeded, or null for a default/miss. | zh-hant-tw |
matchedCandidate nullable | string | Normalized input-form fallback candidate whose original or canonical equivalent matched. | zh-hant |
usedDefault | boolean | Whether the explicit default supplied the result. | false |
ranges string[] Validated lowercase priority ranges.
example: ["zh-hant-tw","zh-hant","zh"]
available string[] Canonical, de-duplicated available tags.
example: ["en","zh","zh-Hant"]
match string nullable Selected available tag, explicit default, or null.
example: zh-Hant
matchedRange string nullable Normalized lowercase input priority range that succeeded, or null for a default/miss.
example: zh-hant-tw
matchedCandidate string nullable Normalized input-form fallback candidate whose original or canonical equivalent matched.
example: zh-hant
usedDefault boolean Whether the explicit default supplied the result.
example: false
/api/language-tags/lookup?ranges=zh-Hant-TW%2Czh&available=en%2Czh%2Czh-Hant {
"data": {
"ranges": [
"zh-hant-tw",
"zh"
],
"available": [
"en",
"zh",
"zh-Hant"
],
"match": "zh-Hant",
"matchedRange": "zh-hant-tw",
"matchedCandidate": "zh-hant",
"usedDefault": false
},
"meta": {
"endpoint": "language-tags",
"route": "/lookup",
"params": {
"ranges": [
"zh-hant-tw",
"zh"
],
"available": [
"en",
"zh",
"zh-Hant"
]
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/language-tags/lookup?ranges=da-DK%2Cda&available=en%2Cfr&default=en {
"data": {
"ranges": [
"da-dk",
"da"
],
"available": [
"en",
"fr"
],
"match": "en",
"matchedRange": null,
"matchedCandidate": null,
"usedDefault": true
},
"meta": {
"endpoint": "language-tags",
"route": "/lookup",
"params": {
"ranges": [
"da-dk",
"da"
],
"available": [
"en",
"fr"
],
"default": "en"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/language-tags/lookup?ranges=*%2Cfr-CA&available=en%2Cfr&default=en {
"data": {
"ranges": [
"*",
"fr-ca"
],
"available": [
"en",
"fr"
],
"match": "fr",
"matchedRange": "fr-ca",
"matchedCandidate": "fr",
"usedDefault": false
},
"meta": {
"endpoint": "language-tags",
"route": "/lookup",
"params": {
"ranges": [
"*",
"fr-ca"
],
"available": [
"en",
"fr"
],
"default": "en"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} | Parameter | Type | Default & allowed | Description |
|---|---|---|---|
ranges
required
| list | example: de-CH,de,en | Priority-ordered basic language ranges; at most 20. '*' matches every available tag. |
available
required
| list | example: en-US,de,de-CH-1996,fr | Available BCP 47 tags to canonicalize and filter; at most 100. |
ranges list required Priority-ordered basic language ranges; at most 20. '*' matches every available tag.
available list required Available BCP 47 tags to canonicalize and filter; at most 100.
| Parameter | Type | Default & allowed | Description |
|---|---|---|---|
fields | list | example: ranges,available | Return only these fields (comma-separated). Mutually exclusive with 'exclude'. |
exclude | list | example: matches | Return all fields except these (comma-separated). |
pretty | boolean | default: false example: true | Pretty-print the JSON response. |
unwrap | boolean | default: false example: true | Drop the envelope: return the raw array/object without data/meta wrapper. |
fields list Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude list Return all fields except these (comma-separated).
pretty boolean Pretty-print the JSON response.
unwrap boolean Drop the envelope: return the raw array/object without data/meta wrapper.
| Field | Type | Description | Example |
|---|---|---|---|
ranges | string[] | Validated lowercase priority ranges. | ["de-ch","de","en"] |
available | string[] | Canonical, de-duplicated available tags. | ["en-US","de","de-CH-1996","fr"] |
matches | string[] | Prefix matches ordered by range priority then available input order, without duplicates. | ["de-CH-1996","de","en-US"] |
ranges string[] Validated lowercase priority ranges.
example: ["de-ch","de","en"]
available string[] Canonical, de-duplicated available tags.
example: ["en-US","de","de-CH-1996","fr"]
matches string[] Prefix matches ordered by range priority then available input order, without duplicates.
example: ["de-CH-1996","de","en-US"]
/api/language-tags/filter?ranges=de-CH%2Cde%2Cen&available=en-US%2Cde%2Cde-CH-1996%2Cfr {
"data": {
"ranges": [
"de-ch",
"de",
"en"
],
"available": [
"en-US",
"de",
"de-CH-1996",
"fr"
],
"matches": [
"de-CH-1996",
"de",
"en-US"
]
},
"meta": {
"endpoint": "language-tags",
"route": "/filter",
"params": {
"ranges": [
"de-ch",
"de",
"en"
],
"available": [
"en-US",
"de",
"de-CH-1996",
"fr"
]
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/language-tags/filter?ranges=*&available=EN-us%2Cfr-FR%2Czh-Hant {
"data": {
"ranges": [
"*"
],
"available": [
"en-US",
"fr-FR",
"zh-Hant"
],
"matches": [
"en-US",
"fr-FR",
"zh-Hant"
]
},
"meta": {
"endpoint": "language-tags",
"route": "/filter",
"params": {
"ranges": [
"*"
],
"available": [
"en-US",
"fr-FR",
"zh-Hant"
]
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} /api/language-tags/filter?ranges=ja&available=en%2Cfr%2Cde {
"data": {
"ranges": [
"ja"
],
"available": [
"en",
"fr",
"de"
],
"matches": []
},
"meta": {
"endpoint": "language-tags",
"route": "/filter",
"params": {
"ranges": [
"ja"
],
"available": [
"en",
"fr",
"de"
]
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
} Canonicalizes well-formed BCP 47 language tags, exposes their language, script, region, extension and private-use components, and implements the two RFC 4647 operations developers most often need: lookup and basic filtering.
Canonicalization uses the Worker's standards-based Intl runtime, plus RFC 5646's fixed grandfathered-tag and private-use-only forms. Deprecated tags with a Preferred-Value, such as i-klingon, resolve to that preferred tag. This endpoint deliberately makes no completeness claim for language, script, region or variant assignment in the live IANA Language Subtag Registry: structurally valid private or unassigned subtags can be accepted.
Matching is case-insensitive and bounded to 20 priority ranges × 100 available tags. Each normalized input range and lookup fallback candidate is compared in both its input and safely canonicalized form, so deprecated aliases match their preferred available tags without rewriting the echoed input ranges. Basic filtering returns every prefix match in range-priority then input order. Lookup searches for an exact tag and progressively removes rightmost subtags, removing a singleton with its nearest trailing subtag; * is skipped and an optional explicit default is returned only after every range fails. Available tags are canonicalized and duplicate canonical forms keep their first position.
No. It validates and canonicalizes supported BCP 47 structure but does not claim that every language, region or variant is currently assigned by IANA.
Lookup returns one exact available tag after progressively truncating each priority range. Basic filtering returns every tag equal to a range or beginning with that range plus a hyphen.
Yes. RFC 5646's fixed grandfathered forms are recognized, preferred replacements are applied where defined, and private-use-only tags such as x-team are lowercased.
All 249 ISO 3166-1 countries and territories with codes, regions, capitals, currencies, languages, calling codes, flags and label-safe land points.
The current IANA delegated TLD ASCII list — search all labels, filter punycode IDNs, or look up one TLD with an honest 404.
Realistic, coherent browser user agents — filter by browser, OS and device; impossible combos like Safari-on-Windows get a clear 400, never a fake string.
Random internet building blocks — valid IPv4/IPv6 addresses, locally-administered MACs, non-resolvable .test domains and URLs, slugs, ports and TLDs.