Skip to content
SEOInternationalization2 credits

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

POST/api/v1/tools/localization
Auth Required
1 req/s on Free plan
2 credits

Parameters

NameTypeRequiredDefaultDescription
url
stringRequired-
The page to audit. Must be a valid absolute http or https URL.
Example: https://example.com/pricing
target_language
stringOptional-
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
stringOptional-
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
booleanOptionaltrue
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
booleanOptionaltrue
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
booleanOptionalfalse
Read the `geo.region` and `geo.position` meta tags. The `geo_targeting` object is absent unless you ask for it.
Example: true
timeout
numberOptional10000
Fetch timeout in milliseconds, between 1000 and 30000.
Example: 10000
respect_robots
booleanOptionaltrue
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

html_lang
The lang attribute on the <html> element — what the page claims to be. null when absent.
content_language_header
The Content-Language response header. Independent of the HTML, and frequently contradicts it.
alternate_languages
Every <link rel="alternate" hreflang="…">, in document order. x-default is returned like any other entry.
detected_language
Trigram detection over the page's visible text, with scripts and styles stripped. This is evidence, not a declaration.

What localization does not do

Request Examples

terminalBash
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

200 OK420ms
{
"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
}
Field Descriptions
data.detected_languageISO 639-1 code detected from the visible text, or `und`. Compare it against `html_lang` — a mismatch is the finding
data.html_langThe `lang` attribute exactly as written, region subtag included. `null` if the page has none
data.content_language_headerThe `Content-Language` response header, or `null`
data.alternate_languagesEvery hreflang alternate, in document order. Attribute order inside each tag does not matter
data.language_countLength of `alternate_languages` — not a count of distinct languages
data.is_multilingualTrue when at least one hreflang alternate was found
data.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 that
data.geo_targeting.positionRaw `geo.position` content, conventionally `latitude;longitude`
credits_usedFixed 2 credits per URL

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

Credit Cost

2 credits
2 credits per URL
Flat rate for one page, whichever signals you enable. Failed calls are not charged.

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: 100,000 credits = 50,000 URLs ($99/mo)

Related Tools