---
title: "Parse a user-agent string"
method: GET
path: "/user-agent/v1"
tags: ["User Agent"]
---

# Parse a user-agent string

`GET /user-agent/v1`

Parses a user-agent string into a structured record: client (with its type, version, maker, rendering engine, and browser-family flags), the operator the traffic acts for, os, device, and classification flags like is_bot and is_ai_crawler. Supply the string via the ua query parameter, or omit it to parse the request's own User-Agent header ("what browser am I?"). Parsing is first-party: the strings you submit are never forwarded to a third-party service. A leaf the string doesn't reveal ships as null, and a block whose every leaf resolved null collapses to a single null (os, client.engine, operator, and any maker), so guard those before reading into them. See https://restcountries.com/docs/user-agent for the full reference.

## Query parameters

- `ua` string
- `response_fields` string
- `response_fields_omit` string
- `pretty` boolean

## Response `200`

Parse record for the resolved user-agent string, always a single object.

- UserAgentParseResponse
  - `data` object, required
    - `objects` UserAgentRecord[], required
      - `ua` string — The user-agent string that was analyzed.
      - `label` string, nullable — Display-ready summary: the client name plus the one context that best identifies the traffic — recognized hardware when the device is something other than a desktop ("Mobile Safari on Apple iPhone"), otherwise the OS ("Chrome on macOS"), and the bare client name when neither resolved ("GPTBot"). Null only when the client name itself didn't parse.
      - `client` object — The agent itself. Always an object.
        - `label` string, nullable — Display-ready client summary, maker-first with the major version (e.g. "Google Chrome (v150)").
        - `name` string, nullable — Client name (e.g. Chrome, Mobile Safari, Googlebot, curl).
        - `type` 'browser' | 'cli' | 'crawler' | 'desktop_app' | 'email' | 'fetcher' | 'library' | 'media_player' | 'mobile_app' | 'null', nullable
        - `version` VersionBlock, nullable — A parsed version as {full, major}. major is a derived integer parsed from full's leading digits. The whole block collapses to a single null when no version was parsed.
          - `full` string, nullable
          - `major` integer, nullable
        - `maker` UserAgentMaker, nullable — The organization that makes the thing this block names (the browser, the engine, the OS, the hardware), resolved from the block's own name. Distinct from the root operator, which is who the traffic acts for: an Instagram webview has engine maker Google and operator Meta. Collapses to a single null when the name matched no known organization.
          - `name` string, nullable
          - `links` UserAgentLinks, nullable — Reference links for an organization. Collapses to a single null when neither link resolved.
            - `wikipedia` string, uri, nullable
            - `official` string, uri, nullable
        - `engine` UserAgentEngine, nullable — The client's rendering engine. Reported as the string claims it, so a bot borrowing browser tokens shows the engine those tokens name. Collapses to a single null when nothing about the engine parsed.
          - `label` string, nullable — Display-ready engine summary, maker-first with the major version (e.g. "Google Blink (v150)").
          - `name` string, nullable — Engine name (e.g. Blink, WebKit, Gecko, Trident).
          - `version` VersionBlock, nullable — A parsed version as {full, major}. major is a derived integer parsed from full's leading digits. The whole block collapses to a single null when no version was parsed.
            - `full` string, nullable
            - `major` integer, nullable
          - `maker` UserAgentMaker, nullable — The organization that makes the thing this block names (the browser, the engine, the OS, the hardware), resolved from the block's own name. Distinct from the root operator, which is who the traffic acts for: an Instagram webview has engine maker Google and operator Meta. Collapses to a single null when the name matched no known organization.
            - `name` string, nullable
            - `links` UserAgentLinks, nullable — Reference links for an organization. Collapses to a single null when neither link resolved.
              - …
        - `attributes` object — Browser-family flags, matched across variants (e.g. Mobile Safari counts as is_safari, Chrome Headless as is_chrome). Always an object, and every leaf is a definite boolean: a flag nothing spoke to answers false, never null.
          - `is_android` boolean — The client is the stock Android Browser. This names the client, not the OS: Chrome on Android is is_chrome, not is_android.
          - `is_chrome` boolean — Chrome family (Chrome, Chrome Mobile, Chrome Headless, Chrome WebView). Excludes Chromium, which has its own flag.
          - `is_chromium` boolean — The client is Chromium itself.
          - `is_chromium_based` boolean — Built on Chromium: Chrome, Chromium, Edge 79+, or any client whose engine reports Blink (Opera, Vivaldi, Samsung Internet, Brave).
          - `is_edge` boolean
          - `is_safari` boolean — Safari family, including Mobile Safari.
          - `is_firefox` boolean — Firefox family, including Mobile Firefox.
          - `is_headless` boolean — Automation-oriented build (Headless Chrome, PhantomJS, SlimerJS, HtmlUnit, Splash).
          - `is_internet_explorer` boolean — Internet Explorer family, desktop and mobile.
          - `is_opera` boolean — Opera family, including Opera Mini, Mobile, and Touch.
          - `is_web_view` boolean — An in-app browser (Instagram, Facebook, Android WebView) rather than a standalone one. Useful when webviews break OAuth flows or downloads.
      - `operator` UserAgentOperator, nullable — Who the traffic acts for, as opposed to who built the client. Populated for bots and in-app browsers (GPTBot: OpenAI, Instagram: Meta), so "all of OpenAI's traffic" is one comparison whatever the individual agent names. Collapses to a single null for ordinary browsers, whose traffic acts for the human using them.
        - `name` string, nullable — Canonical organization name (e.g. OpenAI), resolved from name_legal against the organization registry, falling back to name_legal verbatim when the producer isn't a known organization.
        - `name_legal` string, nullable — The producer exactly as the string or the vendor data declares it (e.g. "OpenAI OpCo, LLC").
        - `email_address` string, nullable — Contact address the string itself declares (e.g. claudebot@anthropic.com); null when it declares none.
        - `links` object, nullable — Collapses to a single null when neither link resolved.
          - `info` string, uri, nullable — The policy or documentation page the bot declares in its own string (e.g. http://www.google.com/bot.html).
          - `wikipedia` string, uri, nullable — The operator's Wikipedia article, resolved from name.
      - `os` UserAgentOS, nullable — The operating system. Collapses to a single null when the string names no OS, which is the common case for bots.
        - `label` string, nullable — Display-ready OS summary, maker-first with the major version (e.g. "Apple macOS (v10)").
        - `name` string, nullable — OS name (e.g. macOS, Windows, iOS, Android, Ubuntu).
        - `version` VersionBlock, nullable — A parsed version as {full, major}. major is a derived integer parsed from full's leading digits. The whole block collapses to a single null when no version was parsed.
          - `full` string, nullable
          - `major` integer, nullable
        - `maker` UserAgentMaker, nullable — The organization that makes the thing this block names (the browser, the engine, the OS, the hardware), resolved from the block's own name. Distinct from the root operator, which is who the traffic acts for: an Instagram webview has engine maker Google and operator Meta. Collapses to a single null when the name matched no known organization.
          - `name` string, nullable
          - `links` UserAgentLinks, nullable — Reference links for an organization. Collapses to a single null when neither link resolved.
            - `wikipedia` string, uri, nullable
            - `official` string, uri, nullable
      - `device` object — The hardware. Always an object, though every leaf but attributes is null for an agent that identifies no hardware.
        - `label` string, nullable — Display-ready device summary, maker-first (e.g. "Apple iPhone", "Samsung Galaxy S24 Ultra").
        - `name` string, nullable — The hardware model by marketing name where one is known (e.g. iPhone, Galaxy S24 Ultra, Pixel 8), falling back to the model code the string carried.
        - `type` 'appliance' | 'augmented_reality' | 'camera' | 'car' | 'cloud' | 'desktop' | 'e_reader' | 'game_console' | 'handheld' | 'media_player' | 'phone' | 'set_top_box' | 'smart_display' | 'smart_tv' | 'tablet' | 'virtual_reality' | 'voice' | 'watch' | 'null', nullable — Device class. Note phone rather than mobile, and game_console rather than console. desktop is derived: desktop strings don't announce themselves, so it's assigned only when a browser reports a desktop-class OS, which is why bots leave it null.
        - `maker` UserAgentMaker, nullable — The organization that makes the thing this block names (the browser, the engine, the OS, the hardware), resolved from the block's own name. Distinct from the root operator, which is who the traffic acts for: an Instagram webview has engine maker Google and operator Meta. Collapses to a single null when the name matched no known organization.
          - `name` string, nullable
          - `links` UserAgentLinks, nullable — Reference links for an organization. Collapses to a single null when neither link resolved.
            - `wikipedia` string, uri, nullable
            - `official` string, uri, nullable
        - `attributes` object — Form-factor flags, reconciled against the settled type so a record never claims two form factors at once. Always an object, and every leaf is a definite boolean: a flag nothing spoke to answers false, never null. is_mobile is the broadest, covering phones, tablets, cameras, and portable media players.
          - `is_camera` boolean
          - `is_desktop` boolean
          - `is_media_player` boolean
          - `is_mobile` boolean
          - `is_phone` boolean
          - `is_set_top_box` boolean
          - `is_smart_tv` boolean
          - `is_tablet` boolean
          - `is_watch` boolean
          - `is_wearable` boolean — Set alongside is_watch; wearable is not itself a device type.
      - `flags` object — Agent classification. Always an object, and every leaf is a definite boolean: a flag nothing spoke to answers false, never null.
        - `is_ai_assistant` boolean — A known AI assistant fetching one page live on a user's behalf (e.g. ChatGPT-User, Perplexity-User). A person is behind the request, unlike a crawler.
        - `is_ai_crawler` boolean — A known AI training or indexing crawler (e.g. GPTBot, ClaudeBot).
        - `is_bot` boolean — Broad non-human flag; crawlers, fetchers, CLIs, and HTTP libraries all count. The one flag to gate on when you mean "not a person".
        - `is_crawler` boolean — Crawls in bulk rather than fetching on demand, so a link previewer like Twitterbot is is_bot but not is_crawler.
    - `meta` ResultMeta
      - `total` integer, required — Number of objects returned.
      - `request_id` string, required
      - `duration` integer, required — Server-side processing time in milliseconds.

## Other responses

- `400` — Bad request. Malformed parameters or unsupported property.
- `401` — Unauthorized. Missing, invalid, expired, or revoked API key.
- `403` — Forbidden. The account is deleted, disabled, frozen, or pending approval; the request origin isn't in the key's allowed CORS origins; a paid-only field was used as a search, filter, or lookup target on a plan that doesn't include it; a limit above the plan's ceiling but within the paid maximum was requested on a non-paid plan; or the monthly quota has been exceeded past the soft-limit grace period.
- `404` — Not found. The route doesn't match any defined endpoint, the API isn't active, or listing isn't supported for this API version.
- `405` — Method not allowed. Every endpoint is GET-only.
- `410` — Gone. The requested API version is no longer active.
- `429` — Too Many Requests. Sustained traffic above the edge rate limit (20 requests per 10 seconds) is rejected by Cloudflare before the request reaches the API, so this response is generated at the edge and does not carry the standard JSON error envelope. Back off briefly and retry.

## Changes

- **2026-08-01** `87a86bdd79f6` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/restcountries/apis/rest-countries/changes/user-agent/v1/get.md)

---

[API](https://skmtc.dev/restcountries/apis/rest-countries.md) · [All operations](https://skmtc.dev/restcountries/apis/rest-countries/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/restcountries/rest-countries/revisions/87a86bdd79f6/schema)
