> ## Documentation Index
> Fetch the complete documentation index at: https://docs.countrystatecity.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Autocomplete

> Type-ahead search for cities, states, and countries with deterministic ranking and ready-to-display labels

Search cities, states, and countries for a type-ahead / autocomplete UI. Unlike [Fuzzy Search](/api/endpoints/fuzzy-search) — which ranks purely by trigram similarity — autocomplete uses a stricter, deterministic order built for a dropdown: **exact matches first, then starts-with matches, then the closest remaining fuzzy matches**, with population and then record ID breaking any ties. The same query always returns the same order. Each result also carries a ready-to-display `label` (e.g. `"Mumbai, Maharashtra, India"`) so you don't have to assemble one yourself.

<Note>**Availability:** Professional and Business plans. Returns `403` on Community, Starter, Supporter, and Legacy plans. [Compare plans](https://countrystatecity.in/pricing?source=playground\&campaign=autocomplete_api), or see **Trying it without a paid plan** below.</Note>

<Info>Matching checks the English name, native name, and stored translations. Translation matching starts at 3 characters. Responses are cached separately by query, filters, plan, locale, and translation output.</Info>

## Authentication

<ParamField header="X-CSCAPI-KEY" type="string" required>
  Your API key for authentication
</ParamField>

## Query Parameters

<ParamField query="q" type="string" required>
  The search text. 2–100 characters, matched case-insensitively against the English and native names.
</ParamField>

<ParamField query="type" type="string" default="city">
  What to search. One of `city`, `state`, or `country`.
</ParamField>

<ParamField query="country" type="string">
  Restrict results to a single country by ISO 3166-1 alpha-2 code, e.g. `IN`, `US`. Case-insensitive (auto-uppercased). Not valid with `type=country` — sending it returns `400`.
</ParamField>

<ParamField query="state" type="string">
  Restrict city results to one state. This works only with `type=city` and requires `country`. Other combinations return `400` because state codes aren't unique across countries.
</ParamField>

<ParamField query="limit" type="integer" default="10">
  Maximum number of results to return. 1–50.
</ParamField>

<ParamField query="locale" type="string">
  Add `localized_name` and `matched_locale`, and use the localized name in `label`. Example: `ja` or `pt-BR`. Professional and Business plans only. See [Localized Place Names](/api/localization).
</ParamField>

<ParamField query="include_translations" type="boolean" default="false">
  Include the full raw `translations` JSON string. Professional and Business plans only.
</ParamField>

## Response

Returns an array. Each item carries the standard fields for the entity (`city`, `state`, or `country`) at your plan's data-access level, plus:

<ResponseField name="type" type="string">
  Which entity this result is: `country`, `state`, or `city`.
</ResponseField>

<ResponseField name="label" type="string">
  A ready-to-display string: just the name for a country, `"State, Country"` for a state, `"City, State, Country"` for a city. Missing parts (e.g. a city with no state on record) are omitted rather than left blank.
</ResponseField>

<ResponseField name="match_score" type="number">
  Trigram similarity of the best-matching name (English or native), from `0` to `1`, rounded to 2 decimals.
</ResponseField>

<ResponseField name="matched_field" type="string">
  Which name field matched: `name`, `native`, or `translation`.
</ResponseField>

<ResponseField name="localized_name" type="string">
  The display name for `locale`, when requested and available on your plan.
</ResponseField>

<ResponseField name="matched_locale" type="string">
  The locale used for `localized_name`, including fallback values such as `native` or `en`.
</ResponseField>

<Note>
  City results always include `country_code` and `state_code`, regardless of your plan's data-access level — even the basic-tier field set includes them here, since you can't build a useful `label` or scope a follow-up request without them. (States already include `country_code` at every tier under the normal field rules, so no such exception is needed there.)
</Note>

## Ranking

Results are ordered deterministically — the same query always returns the same order:

| Priority | Rule                                                 |
| -------- | ---------------------------------------------------- |
| 1        | Exact match (case-insensitive) on `name` or `native` |
| 2        | Starts-with match on `name` or `native`              |
| 3        | Closest remaining fuzzy match, by `match_score`      |
| 4        | Larger `population` breaks ties within the same rank |
| 5        | Lower `id` breaks any remaining tie                  |

<RequestExample>
  ```bash cURL (typo) theme={null}
  curl -X GET 'https://api.countrystatecity.in/v1/search/autocomplete?q=Mumbay&type=city&country=IN' \
    -H 'X-CSCAPI-KEY: YOUR_API_KEY'
  ```

  ```bash cURL (state, scoped to a country) theme={null}
  curl -X GET 'https://api.countrystatecity.in/v1/search/autocomplete?q=Maharashtra&type=state&country=IN' \
    -H 'X-CSCAPI-KEY: YOUR_API_KEY'
  ```

  ```bash cURL (city, scoped to a state) theme={null}
  curl -X GET 'https://api.countrystatecity.in/v1/search/autocomplete?q=Pune&type=city&country=IN&state=MH&limit=5' \
    -H 'X-CSCAPI-KEY: YOUR_API_KEY'
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({ q: 'Mumbay', type: 'city', country: 'IN' });
  const response = await fetch(
    `https://api.countrystatecity.in/v1/search/autocomplete?${params}`,
    { headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' } }
  );

  const results = await response.json();
  results.forEach((r) => console.log(`${r.label} (${r.match_score})`));
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
    'https://api.countrystatecity.in/v1/search/autocomplete',
    params={'q': 'Mumbay', 'type': 'city', 'country': 'IN'},
    headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'}
  )

  for result in response.json():
      print(f"{result['label']} -> {result['match_score']}")
  ```
</RequestExample>

<ResponseExample>
  ```json 200 - City typo match (Professional / Business) theme={null}
  [
    {
      "id": 132332,
      "name": "Mumbai",
      "state_id": 4008,
      "state_code": "MH",
      "country_id": 101,
      "country_code": "IN",
      "latitude": "19.07283000",
      "longitude": "72.88261000",
      "timezone": "Asia/Kolkata",
      "native": "मुंबई",
      "type": "city",
      "label": "Mumbai, Maharashtra, India",
      "match_score": 0.75,
      "matched_field": "name"
    }
  ]
  ```

  ```json 200 - State match theme={null}
  [
    {
      "id": 4008,
      "name": "Maharashtra",
      "iso2": "MH",
      "country_id": 101,
      "country_code": "IN",
      "latitude": "19.75147980",
      "longitude": "75.71388840",
      "timezone": "Asia/Kolkata",
      "type": "state",
      "label": "Maharashtra, India",
      "match_score": 1,
      "matched_field": "name"
    }
  ]
  ```

  ```json 400 - Query too short theme={null}
  {
    "status": "error",
    "message": "Invalid query parameters: q: Search query must be at least 2 characters"
  }
  ```

  ```json 400 - state without country theme={null}
  {
    "status": "error",
    "message": "Invalid query parameters: state: country is required when filtering by state"
  }
  ```

  ```json 400 - state with a non-city type theme={null}
  {
    "status": "error",
    "message": "Invalid query parameters: state: state is only a valid filter when type=city"
  }
  ```

  ```json 403 - Feature Restricted theme={null}
  {
    "status": "error",
    "message": "This feature is not available on your current plan.",
    "details": {
      "feature": "autocomplete",
      "currentTier": "supporter",
      "requiredTier": "professional",
      "upgradeUrl": "https://app.countrystatecity.in/pricing"
    }
  }
  ```
</ResponseExample>

## Trying it without a paid plan

A separate **Playground** plan powers the interactive API documentation — a basic-tier field set on a shared rate limit sized for many concurrent visitors, not a per-visitor quota. It isn't something you can sign up for directly; it is only for the docs playground. For your own integration, [choose a Professional or Business plan](https://countrystatecity.in/pricing?source=playground\&campaign=autocomplete_api).

## Related Endpoints

* [Fuzzy Search](/api/endpoints/fuzzy-search) — pure similarity ranking, without the tiered exact/starts-with/fuzzy order or a computed `label`
* [Get All Countries](/api/endpoints/get-all-countries) — exact/substring inline search via `?q=`
* [Get Cities by Country](/api/endpoints/get-cities-by-country) — list cities, filterable by `?q=`
