Documentation
REST Countries 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.
Try it now
Three steps before you read another word of docs. None require 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();
2. Or run it from your terminal.
Click the snippet to copy, then paste anywhere
curl lives.
curl "https://api.restcountries.com/countries/v5/names.common/Canada" \
-H "Authorization: Bearer rc_live_demo"
3. Trade the demo key for a real one. The demo returns a friendly notice, not the dataset. Sign up for a key with full access: free tier, no card required.
Overview
REST Countries exposes one resource (countries) across a small surface of
endpoints. The dataset covers 80+ 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/jsonon every response. Response shapes follow the conventions of the JSON:API specification: successful payloads sit under a top-leveldatakey (with response metadata nested insidedata.metawhen relevant), and failures come back undererrorsas an array of objects carrying amessage. 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.
Quick start
Sign up to get an API key, then paste this into your terminal:
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.
Authentication
Every Countries endpoint requires an API key. The recommended form is a bearer token in the
Authorization header:
Authorization: Bearer {{your_api_key}}
The bare form (no Bearer prefix) is also accepted for clients
that can't easily inject the scheme:
Authorization: {{your_api_key}}
And as a last resort, the key can be passed as an api-key query
parameter (useful for browser-based experiments), but be aware these can leak into server logs
and browser history:
# Less safe, but supported
curl "https://api.restcountries.com/countries/v5/names.common/Canada?api-key={{your_api_key}}"
Try it without an account
Use the demo key rc_live_demo against any endpoint to verify the API is
reachable. Demo requests return HTTP 200 with the normal response shape, a sample object
when one is available, and a friendly notice: no account required, no quota burn, nothing
logged against any account:
curl "https://api.restcountries.com/countries/v5?api-key=rc_live_demo"
The notice lives under data._demo.message and
data._demo.signup_url, pointing at
restcountries.com/sign-up. Sign up to get a real key with full
access to the dataset.
Browser usage & CORS
Browser-side requests are blocked by default unless the API key allows the page's origin hostname. Add comma-separated hostnames on the API Keys page before using a key from frontend code.
Enter hostnames only, without protocol, port, or path (e.g.
example.com,
app.example.com, or
localhost). IPv4 addresses like
127.0.0.1 are also supported. When the browser sends
Origin: https://app.example.com, the API compares
app.example.com against the API key's allowed hostnames.
Requests without an Origin header are treated as
server-to-server requests and are not affected by CORS settings. The demo key
works from the docs, dashboard, and other supported REST Countries
web origins.
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).
Business-plan customers also get a dedicated EU-region endpoint at a separate
hostname (eu-west-1) for in-region routing.
List
Returns a paginated list of all countries. Defaults to limit=25;
max limit is 100 (anything higher returns
400). Adding q or any searchable
property as a query parameter narrows the list. See Search.
Path examples
Query parameters
limitintegeroffsetintegerqstring{property}stringregion, names.common) used as a
substring filter. Combinable with q and other property
filters; all clauses AND together.
response_fieldsstringresponse_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_omitstringresponse_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) and truthy values
(true, 1)
enable; anything else (including
false and 0)
leaves the response compact.
Example
curl "https://api.restcountries.com/countries/v5?response_fields=names.common,codes.alpha_2,flag.emoji&limit=3" \
-H "Authorization: Bearer {{your_api_key}}"
{
"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
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
Query parameters
q
string
One-of required
400
if explicitly empty (e.g. ?q=).
{property}
string
One-of required
region=Europe,
names.common=ger). Multiple property filters AND together;
combining with q AND-narrows further.
limitintegeroffsetintegerresponse_fieldsstringresponse_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_omitstringresponse_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) and truthy values
(true, 1)
enable; anything else (including
false and 0)
leaves the response compact.
Example
curl "https://api.restcountries.com/countries/v5?q=germ®ion=Europe" \
-H "Authorization: Bearer {{your_api_key}}"
{
"data": {
"objects": [
{ "names.common": "Germany", "region": "Europe", "flag.emoji": "🇩🇪" }
],
"meta": { "total": 1, "count": 1, "limit": 25, "offset": 0, "more": false }
}
}
Aggregate
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:
| Aggregate | Searches across |
|---|---|
name | names.common, names.official,
names.alternates, names.native |
code | codes.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
Query parameters
q
string
Required
400 if explicitly
empty.
limitintegeroffsetintegerresponse_fieldsstringresponse_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_omitstringresponse_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) and truthy values
(true, 1)
enable; anything else (including
false and 0)
leaves the response compact.
Example
curl "https://api.restcountries.com/countries/v5/name?q=can" \
-H "Authorization: Bearer {{your_api_key}}"
{
"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
{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
Query parameters
qstring/region/Europe?q=germ).
limitintegeroffsetintegerresponse_fieldsstringresponse_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_omitstringresponse_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) and truthy values
(true, 1)
enable; anything else (including
false and 0)
leaves the response compact.
Example
curl "https://api.restcountries.com/countries/v5/capitals/Tokyo" \
-H "Authorization: Bearer {{your_api_key}}"
{
"data": {
"objects": [
{ "names.common": "Japan", "codes.alpha_3": "JPN", "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
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
Query parameters
q
string
Required
400 if explicitly empty.
limitintegeroffsetintegerresponse_fieldsstringresponse_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_omitstringresponse_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) and truthy values
(true, 1)
enable; anything else (including
false and 0)
leaves the response compact.
Example
curl "https://api.restcountries.com/countries/v5/names.common?q=ger" \
-H "Authorization: Bearer {{your_api_key}}"
{
"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. Example response bodies in
the endpoint sections abbreviate map-shaped fields
(currencies, languages,
demonyms, etc.) for readability; see each field's type below for
the wire shape.
Data syncs every 4 hours. Fields tagged
dynamic (e.g.
population, leaders,
government_type) are recomputed
on a 4-hour cadence by reconciling values across multiple authoritative upstream sources; the
published value only updates once at least two of those sources agree on it. That extra
confirmation step costs a small amount of latency on breaking changes but means a single bad
feed (a typo, a reverted Wikipedia edit, an upstream outage) won't pollute your response.
Premium data. Fields tagged
premium
are available on Personal plans and above. Free-plan list and read responses replace those
fields with an upgrade notice; free-plan searches or filters against premium fields return
403.
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."
}
]
}
Names
names.common
string
Part of aggregate
names.official
string
Part of aggregate
names.alternates
string[]
Part of aggregate
names.native
object
Part of aggregate
names.translationsobjectcapitalsobject[]demonymsobjectCodes
codes.alpha_2
string
Part of aggregate
codes.alpha_3
string
Part of aggregate
codes.ccn3
string
Part of aggregate
codes.fips
string
Part of aggregate
codes.gec
string
Part of aggregate
codes.cioc
string
Part of aggregate
codes.fifa
string
Part of aggregate
Flag
flag.emoji
string
no read
no search
flag.unicode
string
no read
no search
flag.html_entity
string
no read
no search
flag.url_png
string
no read
no search
flag.url_svg
string
no read
no search
flag.description
string
no read
Geography & people
regionstringsubregionstringcontinentsstring[]landlockedbooleanbordersstring[]area.kilometers
number
no read
no search
area.miles
number
no read
no search
coordinates.lat
number
no read
no search
coordinates.lng
number
no read
no search
timezonesstring[]population
number
dynamic
no read
no search
economy.gini_coefficient
object
no read
no search
languagesarrayCurrencies & calling codes
currenciesobjectcalling_codesstring[]tldsstring[]Cars
cars.driving_sidestringcars.signsstring[]Postal codes
postal_code.format
string
no read
no search
# 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
Calendar & dates
date.start_of_weekstringmonday, sunday,
saturday)
(response example /
read example).
date.academic_year_start.monthintegerdate.academic_year_start.dayintegerdate.fiscal_year_start.government.monthintegerdate.fiscal_year_start.government.dayintegerdate.fiscal_year_start.corporate.monthintegerdate.fiscal_year_start.corporate.dayintegerdate.fiscal_year_start.corporate.basisstringmandated (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.monthintegerdate.fiscal_year_start.personal.dayintegerNumber formatting
number_format.decimal_separatorstring. in the United States and United Kingdom,
, across most of continental Europe)
(response example /
read example).
number_format.thousands_separatorstring, 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).
Classification & memberships
classification.sovereignbooleanclassification.un_memberbooleanclassification.un_observerbooleanclassification.disputedbooleanclassification.dependencybooleanclassification.dependency_typestringcrown_dependency,
overseas_territory,
special_administrative_region, …)
(response example /
read example).
classification.iso_statusstringparent.alpha_2stringparent.alpha_3stringmemberships.unbooleanmemberships.eubooleanmemberships.eurozonebooleanmemberships.schengenbooleanmemberships.natobooleanmemberships.commonwealthbooleanmemberships.oecdbooleanmemberships.g7booleanmemberships.g20booleanmemberships.bricsbooleanmemberships.opecbooleanmemberships.african_unionbooleanmemberships.aseanbooleanmemberships.arab_leaguebooleanGovernment & links
government_type
string
dynamic
no read
leaders
object[]
dynamic
premium
no read
data.leaders
(response example).
links.official
string
no read
no search
links.wikipedia
string
no read
no search
links.open_street_maps
string
no read
no search
links.google_maps
string
no read
no search
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 (1–100, default
25) and offset (default 0). 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 100 (or
below 1) returns 400.
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."
}
]
}
| Status | Meaning |
|---|---|
200 | OK. |
400 | Malformed request: empty
q, out-of-range limit, or another query-parameter validation
failure. |
401 | Missing, unrecognized, revoked, or
expired API key, across both Authorization header and ?api-key=
query-param forms. |
403 | Forbidden. 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. |
404 | Path doesn't match a known endpoint, or the property/aggregate isn't readable / searchable. |
405 | HTTP method not allowed. Countries
endpoints are GET-only. |
410 | API version is no longer active. |
429 | Too Many Requests. Returned by the edge rate limiter when sustained traffic exceeds 20 requests per second. |
500 | Unhandled server error. |
Rate limiting
Separate from your request limit, there's a per-second
ceiling on how quickly you can call the API. Sustained traffic above
20 requests per second is rejected with a
429 Too Many Requests.
This ceiling is enforced by Cloudflare at the edge, in front of the API, so the
429 is returned before the request ever reaches the API
itself. If you hit it, back off briefly and retry. Spreading bursts out under the
per-second ceiling clears it.
Request limits
REST Countries applies an edge throughput limit and a monthly account quota. Sustained
traffic above 20 requests per second is rejected with 429 Too Many Requests
before it reaches the API. Monthly quotas are applied per account and reset on your monthly
billing anniversary (the same day of each month as your sign-up date). The exact monthly cap
depends on your plan:
| Plan | Monthly limit |
|---|---|
| Free | 500 |
| Personal | 25,000 |
| Professional | 100,000 |
| Startup | 200,000 |
| Business | 750,000 |
To change plans (upgrade for a higher monthly cap, or step down if your usage has dropped), head to the Plans page. New ceilings apply immediately on upgrade; existing keys keep serving without re-issuing.
Limits are soft. Going over your monthly cap doesn't immediately stop the
API; we send email alerts at 50%, 80%, and
100% of your cap so overage is never a surprise. After you cross 100% there's a
short grace period during which requests continue to succeed, giving you time to
upgrade or wait for your monthly billing anniversary to reset the quota.
Only if the grace period elapses without an upgrade or reset do subsequent requests start
returning 403 Forbidden: the account is frozen until your next
monthly billing anniversary. As soon as the quota rolls over on that anniversary (or you
upgrade), keys go back to serving immediately. See Account states
for what happens after sustained overage.
Account states
Almost every account stays in the default active state for its
entire lifetime. The states below cover the handful of cases where an account needs a different
posture.
| State | Meaning |
|---|---|
pendingApproval | The account is in a brief manual-review queue
while we confirm the sign-up is genuine. Fewer than 1% of sign-ups land
here, and approval is usually within 12 hours: the account flips to
active automatically once cleared. |
disabled | We've detected malicious activity on the account (key abuse, scraping patterns clearly outside normal use, etc.) and have shut it off. If you think this is in error, contact support and we'll review the situation and reinstate where appropriate. |
frozen | The account has exceeded its monthly request limit by a meaningful margin past the soft-limit grace period. Requests are paused until either the quota rolls over on the next monthly billing anniversary or the account is upgraded to a plan whose ceiling covers the usage. No data is lost; the freeze just blocks new requests. |
Versioning
REST Countries ships breaking changes as a new path version (/v5,
/v6, …). The current version is v5, and it's the
first version we consider long-term stable. Versions
v1–v4 were public iterations and have
been deprecated. See the legacy API deprecation page
for migration guidance.
v5 stays live indefinitely. When a future major version eventually ships (only for a genuine breaking change we can't ship additively), v5 keeps serving alongside it, and the same commitment carries forward to every version after. Anything you build against v5 today doesn't have to follow us forward to keep working.
For the full architectural background (why v1–v4 couldn't be kept stable, what v5's stability promise covers, and how account-holders get notified about new endpoints, fields, and future versions), see /docs/api-versions.
Webhooks
Subscribe one or more URLs to receive a signed POST when REST Countries data changes (e.g. when a
country's leaders updates after an election or its
population shifts after a World Bank refresh). 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.
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.
Data sources
REST Countries' dataset is stitched together from authoritative public registries, multilateral bodies, and well-maintained open-data projects. Static fields are cross-checked against ISO and UN baselines weekly; other fields are synced every 4 hours by reconciling multiple upstream feeds against each other before a value is published. The full list of where every field comes from (registry by registry, with the schema properties each one feeds) lives on its own page.
Acceptable use
REST Countries is designed to power features inside your own product: country pickers, geographic search, dashboards, onboarding flows, anywhere you'd otherwise hand-curate a list of countries. That's exactly what we built it for, and we're happy to see what you ship.
One expectation worth stating plainly: the free tier is meant for evaluation, prototyping, and personal projects. If REST Countries ends up powering something commercial (a product your customers pay for, or a part of how your business operates), we ask that it run on one of the paid plans. That's what funds the data reconciliation and keeps the API fast for everyone.
Two patterns, though, fall outside what's covered by your subscription:
- Snapshotting the dataset for offline use. Caching responses for performance is fine, up to three days, per the Terms. Pulling the full dataset down once and using your local copy from then on isn't.
- Building a competing data product. Using REST Countries inside an app is great. Re-exposing the data as your own API, dataset download, or country-data feed isn't.
If you have an interesting use case that brushes up against either of these, just talk to us. We'd rather hear about it than not, and there's almost always a way to make it work.
Data requests & corrections
Need a field, dataset, or attribute we don't currently expose? We add data based on what customers ask for. Tell us what you'd find useful and we'll consider it for a future release.
Spotted something stale or wrong? Static fields are reviewed weekly against ISO and UN sources, and other fields sync every 4 hours after multi-source reconciliation (see Field reference), but the world moves and feeds occasionally lie. If a value looks off, send it our way: include the country, the property path, what the API returned, and what you believe the correct value is (with a source link if you have one). We'll verify against upstream and ship a correction or roll the offending feed off our reconciliation list.