REST Countries

Docs Countries API

The Countries API is a read-only API for country data. Every endpoint returns JSON, authenticates via a single bearer token, and runs against the same dataset as the demos on the homepage. No SDK is required.

Overview

The Countries API exposes one resource (countries) across a small surface of endpoints. The dataset covers 90+ normalized fields per country (codes, capitals, currencies, languages, borders, geography, memberships, locale conventions, and links). Static fields are reviewed weekly against ISO and UN sources; dynamic fields such as population sync every 4 hours. Premium dynamic fields such as leaders use the same cadence and are available on paid plans.

  • Read-only. All endpoints are GET. There is no POST/PUT/DELETE surface.
  • JSON-only responses. Content-Type: application/json on every response. Response shapes follow the conventions of the JSON:API specification: successful payloads sit under a top-level data key (with response metadata nested inside data.meta when relevant), and failures come back under errors as an array of objects carrying a message. We don't claim strict spec compliance, but if you've worked with JSON:API the shape will feel familiar.
  • Stable v5. Breaking changes will ship as a new version (e.g. /v6), with indefinite support for previous versions. See Versioning.

Try it now

Two ways you can try out the Countries API right now. Neither requires an account.

1. Fire a live request from this page. Click the button below. The response slides open in the Explorer panel.

// Demo key: no account required.
const response = await fetch(
  'https://api.restcountries.com/countries/v5/names.common/Canada',
  { headers: { 'Authorization': 'Bearer rc_live_demo' } }
);
const data = await response.json();

Run this request →

2. Run it from your terminal. Click the copy button below, then paste anywhere curl lives.

curl "https://api.restcountries.com/countries/v5/names.common/Canada?pretty=1" \
  -H "Authorization: Bearer rc_live_demo"

The demo key returns a real, correctly-shaped sample plus a data._demo notice block; it never touches your account or quota.

Quick start

Sign up to get an API key, then paste this into your terminal (swap out the API key placeholder):

curl "https://api.restcountries.com/countries/v5/names.common/Canada" \
  -H "Authorization: Bearer YOUR_API_KEY"

You'll get a single-record data.objects array back. From there, jump to the endpoint sections for the full surface, or browse the Field reference to see what's in each record.

Base URL & versioning

All endpoints live under:

https://api.restcountries.com/countries/v5

The v5 path segment is the API version. REST Countries commits to backwards-compatible additions within a major version (new fields, new endpoints, new query params). See Versioning.

Append ?pretty to any request to pretty-print the JSON response, which is handy while exploring from a browser or terminal.

Business-plan customers also get a dedicated EU-region endpoint at a separate hostname (eu-west-1) for in-region routing.

List

GET /countries/v5

Returns a paginated list of all countries. Defaults to limit=25; max limit is 100 on the free plan, or up to 500 on a paid plan. Adding q or any searchable property as a query parameter narrows the list. See Search.

Path examples

Default page (limit=25, offset=0)
GET /countries/v5 Run →
Smaller page
GET /countries/v5?limit=25 Run →
Pagination: second page of 25
GET /countries/v5?limit=25&offset=25 Run →
Pretty-print the response
GET /countries/v5?pretty Run →
Maximum free-plan page size (limit=100)
GET /countries/v5?limit=100 Run →
Deeper offset (skip the first 100, take 50)
GET /countries/v5?limit=50&offset=100 Run →
Limit the response shape with response_fields
GET /countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji Run →
Combine response_fields with pretty
GET /countries/v5?response_fields=names.common,flag.emoji&pretty Run →
Trim a heavy branch with response_fields_omit
GET /countries/v5?response_fields_omit=names.translations Run →
Drop multiple branches at once
GET /countries/v5?response_fields_omit=names.translations,leaders Run →
Compose response_fields with response_fields_omit (omit wins)
GET /countries/v5?response_fields=names&response_fields_omit=names.translations Run →
Filter by a single property
GET /countries/v5?region=Europe Run →
AND-narrow with multiple property filters
GET /countries/v5?region=Europe&memberships.eu=1 Run →

Query parameters

limitinteger
1–100 on the free plan, or up to 500 on a paid plan. Defaults to 25.
offsetinteger
Skip this many records before returning. Defaults to 0.
qstring
Free-text search across every searchable property. See Search.
{property}string
Any searchable property (e.g. region, names.common) used as a substring filter. Combinable with q and other property filters; all clauses AND together.
response_fieldsstring
Allowlist of properties to include in each returned object. When set, the response carries only those properties and nothing else (e.g. response_fields=names.common,codes.alpha_2,flag.emoji returns objects with exactly those three keys). Comma-separated; ordering doesn't matter. Omit the parameter to return every field. See Field reference for the full property list.
response_fields_omitstring
Blocklist of properties to drop from each returned object (e.g. response_fields_omit=names.translations returns the full object minus that branch). Comma-separated dot-paths; ordering doesn't matter. Composes with response_fields: when both are present, the response is first projected to response_fields, then response_fields_omit prunes from that subset (so the omit list wins on conflict).

Useful for trimming heavy nested branches like names.translations without listing every other field you want.
prettyboolean
Pretty-print the JSON response. The bare flag (?pretty) and truthy values (true, 1) enable; anything else (including false and 0) leaves the response compact.

Example

Request
curl "https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3&pretty=1" \
  -H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
  'https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const data = await response.json();
fetch(
  'https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
)
  .then(function (response) { return response.json(); })
  .then(function (data) { console.log(data); });
import requests
response = requests.get(
  'https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3',
  headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()
$ch = curl_init('https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_API_KEY']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
require 'net/http'
require 'json'
uri = URI('https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer YOUR_API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
data = JSON.parse(response.body)
package main
import (
  "encoding/json"
  "io"
  "net/http"
)
req, _ := http.NewRequest("GET", "https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]interface{}
json.Unmarshal(body, &data)
use reqwest::blocking::Client;
use serde_json::Value;
let client = Client::new();
let response = client
  .get("https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3")
  .header("Authorization", "Bearer YOUR_API_KEY")
  .send()?;
let data: Value = response.json()?;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3"))
  .header("Authorization", "Bearer YOUR_API_KEY")
  .GET()
  .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String body = response.body();
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
var data = await client.GetFromJsonAsync<JsonElement>(
  "https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3");
import Foundation
var request = URLRequest(url: URL(string: "https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3")!)
request.addValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let json = try JSONSerialization.jsonObject(with: data)
Response
{
  "data": {
    "objects": [
      { "names": { "common": "Afghanistan" }, "codes": { "alpha_2": "AF" }, "flag": { "emoji": "🇦🇫" } },
      { "names": { "common": "Albania" }, "codes": { "alpha_2": "AL" }, "flag": { "emoji": "🇦🇱" } },
      { "names": { "common": "Algeria" }, "codes": { "alpha_2": "DZ" }, "flag": { "emoji": "🇩🇿" } }
    ],
    "meta": { "total": 249, "count": 3, "limit": 3, "offset": 0, "more": true }
  }
}

Search

GET /countries/v5?q={query}

Free-text search across every searchable property. Substring match, case-insensitive. + and %20 are both decoded as spaces. An empty q returns 400.

Combinable with one or more property filters as /countries/v5?q=...&{property}=... to AND-narrow the result set. For searches scoped to a named property bundle (e.g. all name fields, all code fields), see Aggregate. For a single-property search, see Search by property.

Path examples

Free-text across every searchable property
GET /countries/v5?q=germ Run →
GET /countries/v5?q=federal%20republic Run →
Free-text combined with property filters (all AND together)
GET /countries/v5?q=germ&region=Europe Run →
GET /countries/v5?names.common=ger&names.official=federal Run →
Free-text with pagination
GET /countries/v5?q=can&limit=10 Run →
GET /countries/v5?q=can&limit=10&offset=10 Run →
Free-text with a boolean property filter
GET /countries/v5?q=ger&memberships.eu=1 Run →
Free-text scoped to a subregion
GET /countries/v5?q=stan&subregion=Central%20Asia Run →
Free-text combined with response shape
GET /countries/v5?q=ger&response_fields=names.common,codes.alpha_2,flag.emoji Run →
Free-text minus a heavy branch
GET /countries/v5?q=ger&response_fields_omit=names.translations Run →
Free-text with pretty-printed output
GET /countries/v5?q=ger&pretty Run →

Query parameters

q string One-of required
Free-text search term. Returns 400 if explicitly empty (e.g. ?q=).
{property} string One-of required
Any searchable property used as a substring filter (e.g. region=Europe, names.common=ger). Multiple property filters AND together; combining with q AND-narrows further.
limitinteger
1–100 on the free plan, or up to 500 on a paid plan. Defaults to 25.
offsetinteger
Skip this many matched records.
response_fieldsstring
Allowlist of properties to include in each returned object. When set, the response carries only those properties and nothing else (e.g. response_fields=names.common,codes.alpha_2,flag.emoji returns objects with exactly those three keys). Comma-separated; ordering doesn't matter. Omit the parameter to return every field. See Field reference for the full property list.
response_fields_omitstring
Blocklist of properties to drop from each returned object (e.g. response_fields_omit=names.translations returns the full object minus that branch). Comma-separated dot-paths; ordering doesn't matter. Composes with response_fields: when both are present, the response is first projected to response_fields, then response_fields_omit prunes from that subset (so the omit list wins on conflict).

Useful for trimming heavy nested branches like names.translations without listing every other field you want.
prettyboolean
Pretty-print the JSON response. The bare flag (?pretty) and truthy values (true, 1) enable; anything else (including false and 0) leaves the response compact.

Example

Request
Response
{
  "data": {
    "objects": [
      { "names": { "common": "Germany" }, "region": "Europe", "flag": { "emoji": "🇩🇪" } }
    ],
    "meta": { "total": 1, "count": 1, "limit": 25, "offset": 0, "more": false }
  }
}

Aggregate

GET /countries/v5/{aggregate}?q={query}

Search across a named bundle of properties in one call. An object matches if any one of the underlying properties contains q (substring, case-insensitive). Two aggregates are predefined:

AggregateSearches across
namenames.common, names.official, names.alternates, names.native
codecodes.alpha_2, codes.alpha_3, codes.ccn3, codes.fips, codes.gec, codes.fifa, codes.cioc

Note: names.translations is intentionally excluded from the name aggregate. Translations cover dozens of languages per country, so substring matches there produce too many false positives to be useful in a generic name search. Use Search by property against names.translations directly if you need to query translations specifically.

Empty q returns 400. If the path segment isn't a known aggregate name, the request falls through to Search by property.

Path examples

name: searches names.common / names.official / names.alternates / names.native
GET /countries/v5/name?q=can Run →
GET /countries/v5/name?q=federal%20republic Run →
GET /countries/v5/name?q=ger&limit=5 Run →
code: searches every codes.* variant (alpha_2, alpha_3, fips, gec, ccn3, fifa, cioc)
GET /countries/v5/code?q=usa Run →
GET /countries/v5/code?q=de Run →
name: paginate deeper into the matched set
GET /countries/v5/name?q=land&limit=10&offset=10 Run →
name: limit the response shape with response_fields
GET /countries/v5/name?q=ger&response_fields=names.common,codes.alpha_2,flag.emoji Run →
name: drop the heavy translations branch
GET /countries/v5/name?q=can&response_fields_omit=names.translations Run →
name: pretty-printed
GET /countries/v5/name?q=can&pretty Run →
code: short string with limit
GET /countries/v5/code?q=ca&limit=10 Run →
code: limit the response shape
GET /countries/v5/code?q=br&response_fields=names.common,codes.alpha_3,codes.fifa Run →

Query parameters

q string Required
Search term. Required. Substring-matched against the aggregate's underlying property list. Returns 400 if explicitly empty.
limitinteger
1–100 on the free plan, or up to 500 on a paid plan. Defaults to 25.
offsetinteger
Skip this many matched records.
response_fieldsstring
Allowlist of properties to include in each returned object. When set, the response carries only those properties and nothing else (e.g. response_fields=names.common,codes.alpha_2,flag.emoji returns objects with exactly those three keys). Comma-separated; ordering doesn't matter. Omit the parameter to return every field. See Field reference for the full property list.
response_fields_omitstring
Blocklist of properties to drop from each returned object (e.g. response_fields_omit=names.translations returns the full object minus that branch). Comma-separated dot-paths; ordering doesn't matter. Composes with response_fields: when both are present, the response is first projected to response_fields, then response_fields_omit prunes from that subset (so the omit list wins on conflict).

Useful for trimming heavy nested branches like names.translations without listing every other field you want.
prettyboolean
Pretty-print the JSON response. The bare flag (?pretty) and truthy values (true, 1) enable; anything else (including false and 0) leaves the response compact.

Example

Request
curl "https://api.restcountries.com/countries/v5/name?q=can&pretty=1" \
  -H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
  'https://api.restcountries.com/countries/v5/name?q=can',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const data = await response.json();
fetch(
  'https://api.restcountries.com/countries/v5/name?q=can',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
)
  .then(function (response) { return response.json(); })
  .then(function (data) { console.log(data); });
import requests
response = requests.get(
  'https://api.restcountries.com/countries/v5/name?q=can',
  headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()
$ch = curl_init('https://api.restcountries.com/countries/v5/name?q=can');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_API_KEY']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
require 'net/http'
require 'json'
uri = URI('https://api.restcountries.com/countries/v5/name?q=can')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer YOUR_API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
data = JSON.parse(response.body)
package main
import (
  "encoding/json"
  "io"
  "net/http"
)
req, _ := http.NewRequest("GET", "https://api.restcountries.com/countries/v5/name?q=can", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]interface{}
json.Unmarshal(body, &data)
use reqwest::blocking::Client;
use serde_json::Value;
let client = Client::new();
let response = client
  .get("https://api.restcountries.com/countries/v5/name?q=can")
  .header("Authorization", "Bearer YOUR_API_KEY")
  .send()?;
let data: Value = response.json()?;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.restcountries.com/countries/v5/name?q=can"))
  .header("Authorization", "Bearer YOUR_API_KEY")
  .GET()
  .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String body = response.body();
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
var data = await client.GetFromJsonAsync<JsonElement>(
  "https://api.restcountries.com/countries/v5/name?q=can");
import Foundation
var request = URLRequest(url: URL(string: "https://api.restcountries.com/countries/v5/name?q=can")!)
request.addValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let json = try JSONSerialization.jsonObject(with: data)
Response
{
  "data": {
    "objects": [
      { "names": { "common": "Canada" }, "flag": { "emoji": "🇨🇦" } },
      { "names": { "common": "Cape Verde" }, "flag": { "emoji": "🇨🇻" } },
      { "names": { "common": "Cameroon" }, "flag": { "emoji": "🇨🇲" } }
    ],
    "meta": { "total": 3, "count": 3, "limit": 25, "offset": 0, "more": false }
  }
}

Read by property

GET /countries/v5/{property}/{value}
Exact match (case-insensitive). The {value} segment must equal the property's value in full. For substring matching, use Search by property.

Look up countries by any readable property. Works equally well for unique identifiers (codes.alpha_2/CA, names.common/Canada), group properties (region/Europe), and reverse lookups on array fields (borders/CAN returns the countries that border Canada). + and %20 are both decoded as spaces, so capitals/new+delhi, capitals/new%20delhi, and capitals/new delhi all resolve.

Append ?q=... to further narrow the matched set against the searchable properties (e.g. /region/Europe?q=germ).

Path examples

By ISO code (alpha-2 / alpha-3)
GET /countries/v5/codes.alpha_2/CA Run →
GET /countries/v5/codes.alpha_3/CAN Run →
By common name (+ and %20 both decode as spaces)
GET /countries/v5/names.common/Canada Run →
GET /countries/v5/names.common/United+States Run →
GET /countries/v5/names.common/United%20Kingdom Run →
By region or subregion (case-insensitive)
GET /countries/v5/region/Europe Run →
GET /countries/v5/subregion/Northern%20Europe Run →
Reverse lookup on an array property (e.g. countries that border Canada)
GET /countries/v5/borders/CAN Run →
GET /countries/v5/currencies/CAD Run →
GET /countries/v5/calling_codes/44 Run →
By capital city
GET /countries/v5/capitals/Tokyo Run →
GET /countries/v5/capitals/new+delhi Run →
By boolean property: pass true or false
GET /countries/v5/landlocked/true Run →
GET /countries/v5/memberships.eu/true Run →
Combined with q to narrow the matched set
GET /countries/v5/region/Europe?q=germ Run →

Query parameters

qstring
Optional. Substring-narrows the matched set against searchable properties (e.g. /region/Europe?q=germ).
limitinteger
1–100 on the free plan, or up to 500 on a paid plan. Defaults to 25.
offsetinteger
Skip this many matched records.
response_fieldsstring
Allowlist of properties to include in each returned object. When set, the response carries only those properties and nothing else (e.g. response_fields=names.common,codes.alpha_2,flag.emoji returns objects with exactly those three keys). Comma-separated; ordering doesn't matter. Omit the parameter to return every field. See Field reference for the full property list.
response_fields_omitstring
Blocklist of properties to drop from each returned object (e.g. response_fields_omit=names.translations returns the full object minus that branch). Comma-separated dot-paths; ordering doesn't matter. Composes with response_fields: when both are present, the response is first projected to response_fields, then response_fields_omit prunes from that subset (so the omit list wins on conflict).

Useful for trimming heavy nested branches like names.translations without listing every other field you want.
prettyboolean
Pretty-print the JSON response. The bare flag (?pretty) and truthy values (true, 1) enable; anything else (including false and 0) leaves the response compact.

Example

Request
curl "https://api.restcountries.com/countries/v5/capitals/Tokyo?pretty=1" \
  -H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
  'https://api.restcountries.com/countries/v5/capitals/Tokyo',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const data = await response.json();
fetch(
  'https://api.restcountries.com/countries/v5/capitals/Tokyo',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
)
  .then(function (response) { return response.json(); })
  .then(function (data) { console.log(data); });
import requests
response = requests.get(
  'https://api.restcountries.com/countries/v5/capitals/Tokyo',
  headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()
$ch = curl_init('https://api.restcountries.com/countries/v5/capitals/Tokyo');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_API_KEY']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
require 'net/http'
require 'json'
uri = URI('https://api.restcountries.com/countries/v5/capitals/Tokyo')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer YOUR_API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
data = JSON.parse(response.body)
package main
import (
  "encoding/json"
  "io"
  "net/http"
)
req, _ := http.NewRequest("GET", "https://api.restcountries.com/countries/v5/capitals/Tokyo", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]interface{}
json.Unmarshal(body, &data)
use reqwest::blocking::Client;
use serde_json::Value;
let client = Client::new();
let response = client
  .get("https://api.restcountries.com/countries/v5/capitals/Tokyo")
  .header("Authorization", "Bearer YOUR_API_KEY")
  .send()?;
let data: Value = response.json()?;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.restcountries.com/countries/v5/capitals/Tokyo"))
  .header("Authorization", "Bearer YOUR_API_KEY")
  .GET()
  .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String body = response.body();
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
var data = await client.GetFromJsonAsync<JsonElement>(
  "https://api.restcountries.com/countries/v5/capitals/Tokyo");
import Foundation
var request = URLRequest(url: URL(string: "https://api.restcountries.com/countries/v5/capitals/Tokyo")!)
request.addValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let json = try JSONSerialization.jsonObject(with: data)
Response
{
  "data": {
    "objects": [
      { "names": { "common": "Japan" }, "codes": { "alpha_2": "JP" }, "flag": { "emoji": "🇯🇵" } }
    ],
    "meta": { "total": 1, "count": 1, "limit": 25, "offset": 0, "more": false }
  }
}

Returns 404 for non-existent or non-readable properties (e.g. population, flag.emoji, government_type). See Field reference for the per-field readable / searchable flags.

Search by property

GET /countries/v5/{property}?q={query}

Substring search within a single searchable property. /countries/v5/names.common?q=ger finds every country whose common name contains "ger". Case-insensitive. An empty q returns 400; a non-existent or non-searchable property returns 404.

Premium searchable properties, such as leaders, are available on Personal plans and above. Free-plan accounts receive 403 when searching or filtering by those properties.

If the path segment is the name of an aggregate (name or code) instead of a real property, the search fans out across that aggregate's underlying property list. See Search.

Path examples

Substring within a single searchable property
GET /countries/v5/names.common?q=ger Run →
GET /countries/v5/names.official?q=republic Run →
Across capitals, accent-tolerant
GET /countries/v5/capitals?q=á Run →
Translations: search a non-English form of the country name
GET /countries/v5/names.translations?q=allemagne Run →
Demonyms: search the people-name forms
GET /countries/v5/demonyms?q=can Run →
Currencies: find every country that uses a currency code
GET /countries/v5/currencies?q=USD Run →
Premium: search by current political leader
GET /countries/v5/leaders?q=macron&response_fields=names.common,leaders Run →
Flag descriptions: search the alt-text style copy
GET /countries/v5/flag.description?q=cross Run →
Combined with response shape
GET /countries/v5/names.common?q=is&response_fields=names.common,codes.alpha_2,flag.emoji Run →
Trim a heavy branch with response_fields_omit
GET /countries/v5/names.common?q=germ&response_fields_omit=names.translations Run →
Aggregate names: fan out across multiple properties
GET /countries/v5/name?q=ger Run →
GET /countries/v5/code?q=de Run →

Query parameters

q string Required
Search term. Required. Substring-matched against the property in the path. Returns 400 if explicitly empty.
limitinteger
1–100 on the free plan, or up to 500 on a paid plan. Defaults to 25.
offsetinteger
Skip this many matched records.
response_fieldsstring
Allowlist of properties to include in each returned object. When set, the response carries only those properties and nothing else (e.g. response_fields=names.common,codes.alpha_2,flag.emoji returns objects with exactly those three keys). Comma-separated; ordering doesn't matter. Omit the parameter to return every field. See Field reference for the full property list.
response_fields_omitstring
Blocklist of properties to drop from each returned object (e.g. response_fields_omit=names.translations returns the full object minus that branch). Comma-separated dot-paths; ordering doesn't matter. Composes with response_fields: when both are present, the response is first projected to response_fields, then response_fields_omit prunes from that subset (so the omit list wins on conflict).

Useful for trimming heavy nested branches like names.translations without listing every other field you want.
prettyboolean
Pretty-print the JSON response. The bare flag (?pretty) and truthy values (true, 1) enable; anything else (including false and 0) leaves the response compact.

Example

Request
curl "https://api.restcountries.com/countries/v5/names.common?q=ger&pretty=1" \
  -H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
  'https://api.restcountries.com/countries/v5/names.common?q=ger',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const data = await response.json();
fetch(
  'https://api.restcountries.com/countries/v5/names.common?q=ger',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
)
  .then(function (response) { return response.json(); })
  .then(function (data) { console.log(data); });
import requests
response = requests.get(
  'https://api.restcountries.com/countries/v5/names.common?q=ger',
  headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()
$ch = curl_init('https://api.restcountries.com/countries/v5/names.common?q=ger');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer YOUR_API_KEY']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
require 'net/http'
require 'json'
uri = URI('https://api.restcountries.com/countries/v5/names.common?q=ger')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer YOUR_API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
data = JSON.parse(response.body)
package main
import (
  "encoding/json"
  "io"
  "net/http"
)
req, _ := http.NewRequest("GET", "https://api.restcountries.com/countries/v5/names.common?q=ger", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]interface{}
json.Unmarshal(body, &data)
use reqwest::blocking::Client;
use serde_json::Value;
let client = Client::new();
let response = client
  .get("https://api.restcountries.com/countries/v5/names.common?q=ger")
  .header("Authorization", "Bearer YOUR_API_KEY")
  .send()?;
let data: Value = response.json()?;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.restcountries.com/countries/v5/names.common?q=ger"))
  .header("Authorization", "Bearer YOUR_API_KEY")
  .GET()
  .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String body = response.body();
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
var data = await client.GetFromJsonAsync<JsonElement>(
  "https://api.restcountries.com/countries/v5/names.common?q=ger");
import Foundation
var request = URLRequest(url: URL(string: "https://api.restcountries.com/countries/v5/names.common?q=ger")!)
request.addValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let json = try JSONSerialization.jsonObject(with: data)
Response
{
  "data": {
    "objects": [
      { "names": { "common": "Germany" }, "flag": { "emoji": "🇩🇪" } },
      { "names": { "common": "Niger" }, "flag": { "emoji": "🇳🇪" } },
      { "names": { "common": "Nigeria" }, "flag": { "emoji": "🇳🇬" } },
      { "names": { "common": "Algeria" }, "flag": { "emoji": "🇩🇿" } }
    ],
    "meta": { "total": 4, "count": 4, "limit": 25, "offset": 0, "more": false }
  }
}

Field reference

Every country record carries the following fields. Static fields are sourced from ISO, UN, and Wikidata and reviewed weekly (see Data sources for the full list of registries we cross-check against). Dynamic fields (e.g. population, leaders, government_type) are recomputed on a 4-hour cadence (by reconciling values across multiple authoritative upstream sources).

Names

names.common string Part of aggregate
The common name the country is known by (often different than the "official" name) (response example / read example).
names.official string Part of aggregate
The official name the country is known by (often a bit technical) (response example / read example).
names.alternates string[] Part of aggregate
Alternate names the country may be known by (e.g. The D.R.C.) (response example / read example).
names.native object Part of aggregate
Native names for the country, keyed by ISO 639-3 language code, each containing common and official forms (response example / read example).
names.translationsobject
Translations of the country name into other languages, keyed by ISO 639-3 language code, each containing common and official forms (response example / read example).
capitalsobject[]
The capital(s) of the country, each as an object with name, coordinates, and an attributes object of role flags (primary, constitutional, administrative, executive, legislative, judicial). Multi-capital countries set whichever role flag fits each capital; single-capital countries set primary (response example / read example).
demonymsobject
Demonyms for the country, keyed by ISO 639-3 language code, each containing masculine (m) and feminine (f) forms (response example / read example).

Codes

codes.alpha_2 string Part of aggregate
The ISO 2-letter code for the country (response example / read example).
codes.alpha_3 string Part of aggregate
The ISO 3-letter code for the country (response example / read example).
codes.ccn3 string Part of aggregate
The ISO 3166-1 numeric (3-digit) code for the country (response example / read example).
codes.fips string Part of aggregate
The FIPS 2-letter code for the country (less commonly used) (response example / read example).
codes.gec string Part of aggregate
The GEC Entities 2-letter code for the country (less commonly used) (response example / read example).
codes.cioc string Part of aggregate
The 3-letter International Olympic Committee code for the country (response example / read example).
codes.fifa string Part of aggregate
The 3-letter FIFA code used by the international football association body (response example / read example).

Flag

flag.emoji string no read no search
The emoji flag for this country (if it exists) (response example).
flag.unicode string no read no search
Unicode code points that render the flag emoji (e.g. U+1F1FA U+1F1F8) (response example).
flag.html_entity string no read no search
HTML numeric character references that render the flag emoji (response example).
flag.url_png string no read no search
URL to a PNG rendering of the country flag (response example).
flag.url_svg string no read no search
URL to an SVG rendering of the country flag (response example).
flag.description string no read
Plain-language description of the flag (colors, layout, symbols). Suitable for use as alt text on an image rendering of the flag. Empty when no source description is available (response example).
flag.colors.dominant string no read no search
Dominant color of the country flag, as a hex string (response example).
flag.colors.prominent string no read no search
Most prominent color of the country flag — the single color covering the largest share of its area — as a hex string (response example).
flag.colors.palette object[] no read no search
Color palette of the country flag, as an array of {hex, proportion} maps — each entry pairs a hex color with its proportion, the share (0–1) of the flag that color covers (response example).
flag.colors.swatches object no read no search
Semantic color swatches of the country flag, keyed by role (vibrant, muted, dark_vibrant, dark_muted, light_vibrant, light_muted), each a hex string. All six roles are always present; a role the flag has no matching color for is null (response example).

Geography & people

regionstring
The geographic region the country belongs to (e.g. Africa, Americas, Asia, Europe, Oceania) (response example / read example).
subregionstring
The geographic sub-region the country belongs to (e.g. Northern Europe, Southern Asia) (response example / read example).
continentsstring[]
The continent(s) the country is geographically part of (response example / read example).
landlockedboolean
Whether the country has no coastline (is fully enclosed by other land territory) (response example / read example).
bordersstring[]
ISO 3-letter codes of countries that share a land border with this one (response example / read example).
area.kilometers number no read no search
Total land area of the country, in square kilometers (response example).
area.miles number no read no search
Total land area of the country, in square miles (response example).
coordinates.lat number no read no search
Latitude of the country's geographic center, in decimal degrees (response example).
coordinates.lng number no read no search
Longitude of the country's geographic center, in decimal degrees (response example).
timezonesstring[]
UTC offsets observed by the country (e.g. UTC+05:30) (response example / read example).
population number dynamic no read no search
The population of the country, as sourced by official reports published by the country (response example).
economy.gini_coefficient object no read no search
Gini coefficient(s) for the country, keyed by reporting year (response example).
languagesarray
Languages used in the country, each with ISO 639 identifiers, BCP 47 tag, English name, and native name (response example / read example).

Currencies & calling codes

currenciesobject
The currencies that the country officially supports (response example / read example).
calling_codesstring[]
International dialing code(s) for the country (e.g. 1 for the United States, 44 for the United Kingdom) (response example / read example).
tldsstring[]
The TLDs (top-level domains) that are officially associated with the country (response example / read example).

Cars

cars.driving_sidestring
Side of the road traffic drives on: left or right (response example / read example).
cars.signsstring[]
International vehicle registration code(s), the letters on the white oval sticker for cars in international traffic (1949 Geneva and 1968 Vienna conventions). Most countries have a single code; a handful have multiple historical codes (response example / read example).

Postal codes

postal_code.format string no read no search
Human-readable postal-code mask using # for digits and letters as literals (e.g. A#A #A# for Canada). Suitable as an input-field placeholder. Empty when no source data is available or the country does not use postal codes (response example).
postal_code.regex string no read no search
Regular-expression pattern that matches a valid postal code for the country. Suitable for client- or server-side validation. Empty when no source data is available or the country does not use postal codes (response example).

Calendar & dates

date.start_of_weekstring
Conventional first day of the week for the country (e.g. monday, sunday, saturday) (response example / read example).
date.academic_year_start.monthinteger
Month (1–12) the country's academic year typically begins (response example / read example).
date.academic_year_start.dayinteger
Day of the month (1–31) the country's academic year typically begins (response example / read example).
date.fiscal_year_start.government.monthinteger
Month (1–12) the country's government fiscal year begins (response example / read example).
date.fiscal_year_start.government.dayinteger
Day of the month (1–31) the country's government fiscal year begins (response example / read example).
date.fiscal_year_start.corporate.monthinteger
Month (1–12) the most commonly observed corporate fiscal year begins in the country (response example / read example).
date.fiscal_year_start.corporate.dayinteger
Day of the month (1–31) the most commonly observed corporate fiscal year begins in the country (response example / read example).
date.fiscal_year_start.corporate.basisstring
How authoritative the corporate fiscal year value is for the country: mandated (legally fixed), default (a country-recommended date most corporations follow but may opt out of), or convention (no rule; the value is the most common practice) (response example / read example).
date.fiscal_year_start.personal.monthinteger
Month (1–12) the personal/individual tax year begins in the country (response example / read example).
date.fiscal_year_start.personal.dayinteger
Day of the month (1–31) the personal/individual tax year begins in the country (response example / read example).

Number formatting

number_format.decimal_separatorstring
Character used to separate the integer and fractional parts of a number (e.g. . in the United States and United Kingdom, , across most of continental Europe) (response example / read example).
number_format.thousands_separatorstring
Character (or characters) used to separate groups of thousands in a number (e.g. , in the United States, . in Germany, a non-breaking space in France, ' in Switzerland). Empty when the country does not use a thousands separator (response example / read example).

Units

units.measurement_systemstring
The system of measurement in everyday use (metric almost everywhere, imperial in the United States, Liberia, and Myanmar) (response example / read example).
units.temperature_scalestring
The temperature scale in everyday use (Celsius in most of the world, Fahrenheit in the United States and a handful of other territories) (response example / read example).

Classification & memberships

classification.sovereignboolean
Whether the entity is sovereign (self-governing, recognized or not) (response example / read example).
classification.un_memberboolean
Whether the entity is a full UN member state (response example / read example).
classification.un_observerboolean
Whether the entity is a UN permanent observer state (response example / read example).
classification.disputedboolean
Whether the entity has contested or limited international recognition (response example / read example).
classification.dependencyboolean
Whether the entity is a dependent territory belonging to another state (response example / read example).
classification.dependency_typestring
For dependent entities, the kind of dependency (e.g. crown_dependency, overseas_territory, special_administrative_region, …) (response example / read example).
classification.iso_statusstring
ISO 3166-1 code assignment kind (official or user_assigned) (response example / read example).
parent.alpha_2string
For dependent entities, the sovereign parent country's ISO alpha-2 code (response example / read example).
parent.alpha_3string
For dependent entities, the sovereign parent country's ISO alpha-3 code (response example / read example).
memberships.unboolean
Whether the entity is a full UN member state (response example / read example).
memberships.euboolean
Whether the entity is a European Union member state (response example / read example).
memberships.eurozoneboolean
Whether the entity uses the euro as its official currency (response example / read example).
memberships.schengenboolean
Whether the entity is part of the Schengen Area (response example / read example).
memberships.natoboolean
Whether the entity is a NATO member (response example / read example).
memberships.commonwealthboolean
Whether the entity is a member of the Commonwealth of Nations (response example / read example).
memberships.oecdboolean
Whether the entity is an OECD member (response example / read example).
memberships.g7boolean
Whether the entity is a G7 member (response example / read example).
memberships.g20boolean
Whether the entity is a G20 member (response example / read example).
memberships.bricsboolean
Whether the entity is a BRICS member (response example / read example).
memberships.opecboolean
Whether the entity is an OPEC member (response example / read example).
memberships.african_unionboolean
Whether the entity is an African Union member (response example / read example).
memberships.aseanboolean
Whether the entity is an ASEAN member (response example / read example).
memberships.arab_leagueboolean
Whether the entity is an Arab League member (response example / read example).

Government & links

government_type string dynamic no read
The type of government in power (response example).
leaders object[] dynamic premium no read
Current political leaders for the country. Each leader includes assets, attributes, links, name, and title fields. Available on Personal plans and above; Free-plan responses return an upgrade notice at data.leaders (response example).
links.official string no read no search
Official link for the country (response example).
links.wikipedia string no read no search
Wikipedia link for the country (response example).
links.open_street_maps string no read no search
OpenStreetMap URL for the country (response example).
links.google_maps string no read no search
Google Maps URL for the country (response example).

Premium Data

Fields tagged premium are available on Personal plans and above.

In broader country responses, the field value is replaced in place. For example, leaders data will show the following (for free plans):

{
  "leaders": [
    {
      "message": "data.leaders is only available on paid plans. Go to https://restcountries.com/plans to make updates to your account."
    }
  ]
}

Direct searches, filters, and lookups against the premium field return an error response. For example, attempt to search or filter by leaders will show the following (for free plans):

{
  "errors": [
    {
      "message": "The leaders field is available only on paid plans and cannot be used as a search, filter, or lookup field on your current plan. Request broader country data to receive the fallback value. Go to https://restcountries.com/plans to make updates to your account."
    }
  ]
}

Sort order

Multi-object responses are returned in a stable order, sorted alphabetically (ascending) by names.common. The same query returns the same objects in the same positions across requests, which means limit and offset can be used to page through a result set without races or duplicates.

Custom sort parameters aren't currently supported. If you have a use case that needs a different order (most populous first, by region then name, etc.), let us know.

Pagination

Every endpoint that returns objects accepts limit and offset (default 0). limit defaults to 25 and can range from 1 to 100 on the free plan, or up to 500 on a paid plan. The response carries a data.meta block describing the slice, so you can iterate without tracking position client-side:

{
  "data": {
    "objects": [ ... ],
    "meta": {
      "total":  249,
      "count":  25,
      "limit":  25,
      "offset": 0,
      "more":   true,
      "request_id": "<request-id>"
    }
  }
}

total is the total matched count after filters; count is the size of the returned slice; more is shorthand for "there are records past this page". Out-of-bounds offsets return an empty objects array (status 200), not a 404. A limit above your plan's ceiling (100 on the free plan, 500 on a paid plan) or below 1 returns an error.

Errors

Error responses use standard HTTP status codes plus a JSON body that names what went wrong. Each entry in the errors array includes a message describing the failure.

{
  "errors": [
    {
      "message": "Limit must be an integer between 1 and 100."
    }
  ]
}
StatusMeaning
200OK.
400Malformed request: empty q, out-of-range limit, or another query-parameter validation failure.
401Missing, unrecognized, revoked, or expired API key, across both Authorization header and ?api-key= query-param forms.
403Forbidden. Returned when the account is frozen (e.g. monthly request limit exceeded), or when a Free-plan account searches or filters by a premium field such as leaders. Frozen accounts clear on the monthly billing anniversary or when you upgrade.
404Path doesn't match a known endpoint, or the property/aggregate isn't readable / searchable.
405HTTP method not allowed. Countries endpoints are GET-only.
410API version is no longer active.
429Too Many Requests. Returned by the edge rate limiter when sustained traffic exceeds 20 requests per 10 seconds.
500Unhandled server error.

Webhooks

Subscribe one or more URLs to receive a signed POST when Countries API data changes: a country's fields updating after a reconciliation cycle (country.updated, country.field.changed), or a country joining or leaving the dataset (country.added, country.removed). Webhooks are a Business plan feature.

Full reference (event types, payload schemas, signature verification, delivery and retry semantics, idempotency, and local testing) lives on its own page: /docs/webhooks.

Free flag CDN

REST Countries also provides a free global CDN for country flag images. It serves 254 flags in PNG, JPG, GIF, and SVG formats, with raster widths from w160 through w2560. Each flag has 45 raster URL variations plus one SVG, which means 11,684 image URLs are available for free across the CDN. No account is needed, no API key is required, and the CDN can be used entirely anonymously.

That keeps teams from having to generate, resize, convert, store, and invalidate thousands of flag image variations themselves.

<img src="https://flags.restcountries.com/v5/w320/ca.png" alt="Canada flag">

Flag requests are delivered from Cloudflare edge nodes with cache rules for stable image URLs, with CloudFront as the fallback source and S3 behind that as the durable origin. The flag CDN is cookie free and GDPR compliant, and it is designed for direct browser use with no tracking.

Open the Flag CDN picker →