localization
Audit how a page declares its language and region. Returns the <html lang> attribute, the Content-Language header, every rel="alternate" hreflang link, the language actually detected from the visible text, and optional geo-targeting meta — so you can see where a site's declarations disagree with its content.
Use Cases
hreflang Audits
Enumerate the alternate-language links a page publishes and check the set is complete and reciprocal across locales.
Catch Mislabelled Pages
Compare html_lang against detected_language. A page that declares en but reads as Spanish is a real SEO defect and this is how you find it.
Competitor Coverage
See which languages a competitor actually ships, straight from their hreflang set, rather than guessing from their URL structure.
Regression Checks in CI
Assert language_count and is_multilingual after a deploy, so a broken i18n build does not quietly ship with half the locales missing.
Geo-Targeting Inventory
Collect geo.region and geo.position meta across a site to see which pages carry regional signals at all.
Localized Response Testing
Send an Accept-Language preference with the request and see whether the server varies what it returns.
Endpoint
/api/v1/tools/localizationParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Required | - | The page to audit. Must be a valid absolute http or https URL. Example: https://example.com/pricing |
target_language | string | Optional | - | Language you expect. Sent as the request's `Accept-Language`, echoed back, and compared against the detected language and `html_lang` to produce `matches_target`. The comparison is exact, so `es` does not match `es-ES`. Example: es |
target_country | string | Optional | - | Country you expect. Echoed back and sent as an `X-Country-Code` request header. That header is a CrawlForge convention rather than a standard, so most servers will ignore it. Example: ES |
detect_language | boolean | Optional | true | Detect the language from the page's visible text. Returns an ISO 639-1 code, or `und` when the text is too short or the language is not recognised. Set false and `detected_language` stays `und`. Example: true |
extract_hreflang | boolean | Optional | true | Collect `rel="alternate"` hreflang links. Set false and `alternate_languages` comes back empty, which also forces `language_count` to 0 and `is_multilingual` to false. Example: true |
check_geo_targeting | boolean | Optional | false | Read the `geo.region` and `geo.position` meta tags. The `geo_targeting` object is absent unless you ask for it. Example: true |
timeout | number | Optional | 10000 | Fetch timeout in milliseconds, between 1000 and 30000. Example: 10000 |
respect_robots | boolean | Optional | true | Respect the target site's robots.txt. Left at `true`, a path disallowed for `CrawlForge` is refused with 403 before anything is fetched and no credits are charged. Set it to `false` only for a target you have your own agreement with — the response then carries a `warnings` entry and the override is recorded against your API key. Example: true |
Signals It Reads
lang attribute on the <html> element — what the page claims to be. null when absent.Content-Language response header. Independent of the HTML, and frequently contradicts it.<link rel="alternate" hreflang="…">, in document order. x-default is returned like any other entry.Request Examples
curl -X POST https://crawlforge.dev/api/v1/tools/localization \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/pricing",
"target_language": "es",
"check_geo_targeting": true
}'Response Example
{ "success": true, "data": { "url": "https://example.com/pricing", "detected_language": "en", "html_lang": "en-US", "content_language_header": "en-US", "alternate_languages": [ { "lang": "en", "url": "https://example.com/pricing" }, { "lang": "es", "url": "https://example.com/es/pricing" }, { "lang": "zh-Hans", "url": "https://example.com/zh-Hans/pricing" }, { "lang": "x-default", "url": "https://example.com/pricing" } ], "language_count": 4, "is_multilingual": true, "target_language": "es", "matches_target": false, "target_country": "ES", "geo_targeted": true, "geo_targeting": { "region": "US-CA", "position": "37.7749;-122.4194", "has_geo_meta": true } }, "credits_used": 2, "credits_remaining": 998, "processing_time": 420}data.detected_languageISO 639-1 code detected from the visible text, or `und`. Compare it against `html_lang` — a mismatch is the findingdata.html_langThe `lang` attribute exactly as written, region subtag included. `null` if the page has nonedata.content_language_headerThe `Content-Language` response header, or `null`data.alternate_languagesEvery hreflang alternate, in document order. Attribute order inside each tag does not matterdata.language_countLength of `alternate_languages` — not a count of distinct languagesdata.is_multilingualTrue when at least one hreflang alternate was founddata.matches_targetTrue when `target_language` equals the detected language or `html_lang`. Exact string comparison, so `es` fails against `es-ES`data.geo_targetedEchoes the `check_geo_targeting` flag you sent. It is not a verdict — read `geo_targeting.has_geo_meta` for thatdata.geo_targeting.positionRaw `geo.position` content, conventionally `latitude;longitude`credits_usedFixed 2 credits per URLError Handling
Invalid URL (400 Bad Request)
VALIDATION_ERROR. url is required and must parse as an absolute URL. The same status covers a timeout outside 1000-30000.
Page Too Large (413 Payload Too Large)
RESPONSE_TOO_LARGE. The page exceeded the 25MB read limit and was refused rather than buffered.
Target Timed Out (504 Gateway Timeout)
FETCH_TIMEOUT. The page stopped responding while sending its body. Raise timeout, up to 30000ms.
Fetch Failed (502 Bad Gateway)
FETCH_FAILED. The response body could not be read — connection reset, or a body that is not decodable text.
Analysis Failed (500 Internal Server Error)
TOOL_ERROR. Nothing is charged for a failed call; credits are deducted only after the audit succeeds.
Blocked by robots.txt (403 Forbidden)
The target site's robots.txt disallows this path for CrawlForge. Set respect_robots: false to override if you have your own agreement with the target — the override is recorded against your API key. The override does not reach a host on CrawlForge's permanent opt-out list, which is refused whatever respect_robots is set to.
<html lang> returns a normal result. Check the target's status separately with fetch_url if that matters to you.Credit Cost
What's Included:
<html lang> and Content-Language extraction
Full rel=alternate hreflang set, in document order
Trigram language detection over the visible text
geo.region and geo.position meta tags
Target-language match verdict
Plan Recommendations:
Free Plan: 1,000 one-time trial credits = 500 URLs
Hobby Plan: 5,000 credits = 2,500 URLs ($19/mo)
Professional Plan: 50,000 credits = 25,000 URLs ($99/mo)