ForHosting KIT · Web Scraping & Monitoring

Parse an Accept-Language header into ordered locale preferences

Accept-Language looks compact, but using it safely means more than splitting a string at commas.

● BetaFree · in your browser
Use it from WebAPIEmailTelegramApp soon

Each language range may carry a quality value, entries with equal weights must retain their original order, and malformed tags should be rejected before they affect content negotiation. This parser converts one header value into a predictable list of locale preferences. It normalizes familiar language, script, and region casing, preserves wildcards, validates quality syntax, and returns the result in descending preference order for routing, testing, logging, or application-level locale selection.

Turn the header into an explicit preference list

An Accept-Language header expresses several choices in a small amount of text. A browser might send a regional locale first, a broader language second, and a wildcard as a final fallback. Reading that value directly inside routing code encourages repeated string handling and inconsistent edge cases. This parser produces a preferences array in which every record has a locale and a numeric quality value. Entries without an explicit quality parameter receive the standard value of 1. The list is sorted from highest to lowest quality, while entries with equal quality remain in the same order in which the sender supplied them. That stable behavior matters because position is the only remaining preference signal when weights match. Common casing is normalized for clearer downstream comparisons: languages are lowercase, two-letter regions are uppercase, and four-letter scripts use title case. The wildcard remains an asterisk so an application can recognize a general fallback without treating it as a specific locale.

Reject ambiguous or malformed input early

Header parsing sits at a trust boundary because the value normally comes from a client. Silent recovery can turn a typo into an unexpected language choice, so the parser rejects malformed input instead of guessing what the sender intended. A language range must begin with an alphabetic subtag and may continue with hyphen-separated alphanumeric subtags. Underscores, spaces inside a tag, empty subtags, and punctuation are invalid. The only wildcard accepted is the complete range represented by an asterisk. A quality parameter must use q followed by a value from 0 through 1, with no more than three decimal places; values above 1, negative values, unknown parameters, and repeated semicolons cause an error. Empty comma-separated entries are also rejected. The input is capped at the declared header length to keep processing bounded. These rules make failures visible at the API boundary and prevent a partially parsed header from quietly selecting content that the client did not actually request.

Apply the parsed result to locale negotiation

The ordered output is designed to be a clean input for your own locale matching policy. Walk through the preferences and compare each locale with the translations your application supports. You may try an exact regional match first, then fall back from a locale such as fr-CA to its base language, and finally use the wildcard or your product default. The parser deliberately does not choose that policy for you: supported locales, regional fallback rules, and the treatment of quality zero depend on the application. Keeping parsing separate from selection makes the behavior easier to test and reuse across gateways, server-rendered pages, APIs, and analytics pipelines. It also helps when diagnosing reports that a visitor received the wrong language, because logs can store the structured preference list rather than an opaque raw header. For automated workloads, each request costs $0.002. The browser version runs the same deterministic parsing logic locally, which is useful for inspecting headers during development without sending their contents elsewhere.

Choose localized content

Convert a browser header into ranked candidates before matching them against the locales your site supports.

Test proxy and client behavior

Inspect whether a browser, SDK, or gateway sends the expected language ranges and quality weights.

Normalize request logs

Store structured locale preferences so language-routing incidents can be searched and compared consistently.

What is returned?

The result contains a preferences array ordered by descending quality. Each entry has a normalized locale string and a numeric quality value.

What happens when q is omitted?

The entry receives a quality value of 1, which is the standard maximum preference.

Are equal-quality entries reordered?

No. Entries with the same quality keep their original relative order.

Does the parser choose one of my supported locales?

No. It parses and ranks the header. Your application remains responsible for exact matching, fallback, and default-locale policy.

Which malformed values cause an error?

Examples include tags with underscores or empty subtags, blank list entries, unknown parameters, and quality values outside 0 through 1 or with more than three decimal places.

How much does an API request cost?

Each API request costs $0.002. The deterministic browser tool can also run locally on this page.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/web/accept-language-parse

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.

curl -X POST https://api.kit.forhosting.com/web/accept-language-parse \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"en-US,en;q=0.9,fr-CA;q=0.7,*;q=0.1"}'
{
  "text": "en-US,en;q=0.9,fr-CA;q=0.7,*;q=0.1"
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "web.accept_language_parse",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.002

Published price — no tokens, no invented credits. A failed task is never charged.

max_chars8192
HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.

Read the full KIT documentation →