REST Countries v3.1 is gone β€” host the countries dataset yourself

If your country-picker, flag quiz, or "where are our users" dashboard just broke: restcountries.com retired all of its legacy versions. Every request to /v1, /v2, /v3, /v3.1, or /v4 now redirects to an error envelope (verified Aug 2026):

{ "success": false,
  "data": null,
  "errors": [{ "message": "This API version has been deprecated. …" }] }

πŸ“‘ Is restcountries.com’s legacy API still dead? We check it (and 36 other classic public mock/placeholder APIs) with a plain GET every 30 minutes β€” it answers HTTP 200, so uptime bots call it β€œup”, but we probe the body for real data. See the live status page.

The nasty part: that error comes back with HTTP 200. So fetch(...).then(r => r.ok) passes, res.json() parses fine, and your app breaks one step later when the array you mapped over is null β€” silently, with no failed request in the network tab to point at. A decade of tutorials, Codecademy-style projects, and Stack Overflow answers built on https://restcountries.com/v3.1/all now fail exactly this way.

There is a new v5 at api.restcountries.com, but it is not a drop-in fix: it requires an account and an API key (Bearer token on every request), the free plan is capped at 1,000 requests per month with a 20-requests-per-10-seconds ceiling, the response shape changed to a JSON:API-style data envelope, and field names moved (name.common β†’ names.common, cca2 β†’ codes.alpha_2, and so on). Their own migration docs estimate a 15–20 minute mapping pass per integration.

For a country picker or a tutorial project, there's a simpler question: why is this an external API dependency at all? Country names, codes, capitals, and flags barely change. Below: one curl that hosts a real 250-country dataset as your own API β€” no key, no monthly cap, CORS on, filters/search/sort/pagination included, and you can edit the data because it's yours.

1. One curl: your own countries API

We host a ready-made countries dataset (250 countries and territories β€” name, official name, ISO codes, capital, region, subregion, area, currency, languages, flag emoji, lat/lng, borders). Pipe it into the importer:

curl -s https://mockbird.mockbird.workers.dev/data/countries.db.json \
| curl -s -X POST 'https://mockbird.mockbird.workers.dev/api/projects/import?name=countries' \
    --data-binary @-

The response has your project id and an adminKey (save it β€” it's how you manage the project or claim it into an account later). Your API is live immediately:

https://mockbird.mockbird.workers.dev/m/YOUR_ID/countries

No signup, no API key, CORS enabled β€” call it straight from browser JavaScript.

2. The queries your old code was doing

Everything restcountries v3.1 tutorials did, mapped to standard query params:

restcountries v3.1Your Mockbird API
/v3.1/all/countries (paginate with _page/_limit; total in X-Total-Count)
/v3.1/name/germany/countries?q=germany (case-insensitive, searches every field)
/v3.1/alpha/JP/countries?code=JP (or ?cca3=JPN)
/v3.1/region/europe/countries?region=Europe
/v3.1/subregion/central%20asia/countries?subregion=Central+Asia
/v3.1/capital/tokyo/countries?capital=Tokyo
?fields=name,capital,flags?select=name,capital,flag
(no equivalent)range filters: ?area_gte=1000000, sort: ?sortBy=area&order=desc

Try them (replace YOUR_ID, or run the import above first):

# the 53 European countries, name + capital + flag only
curl 'https://mockbird.mockbird.workers.dev/m/YOUR_ID/countries?region=Europe&select=name,capital,flag'

# free-text search β€” matches names AND capitals
# (q=stan finds Kazakhstan… and the Falkland Islands, capital Stanley)
curl 'https://mockbird.mockbird.workers.dev/m/YOUR_ID/countries?q=stan&select=name,capital'

# the 7 giants over 7M kmΒ², largest first
curl 'https://mockbird.mockbird.workers.dev/m/YOUR_ID/countries?area_gte=7000000&sortBy=area&order=desc&select=name,area'

# one country by ISO code
curl 'https://mockbird.mockbird.workers.dev/m/YOUR_ID/countries?code=JP'

# the 45 landlocked countries
curl 'https://mockbird.mockbird.workers.dev/m/YOUR_ID/countries?landlocked=true&select=name,region'

3. It's your data now

Unlike an external read-only API, this is a real CRUD backend:

4. Honest comparison

REST Countries v5Your Mockbird project
API keyRequired (Bearer, signup)None
Free requests1,000/month, 20 req/10s10,000/day per project
Response shapeJSON:API-style data envelopePlain array / object (or reshape it)
Data freshnessMaintained β€” weekly ISO/UN review, population synced every 4h, 90+ fields, flag CDNSnapshot β€” static facts (names, codes, capitals, regions, area, flags)
Population dataβœ” live-synced✘ not included (it changes; we won't serve stale numbers as fresh)
Writes / custom fieldsRead-onlyFull CRUD, add any field
Old v3.1 URLsDead (error envelope, HTTP 200)n/a β€” your URLs, they stay up
When to use which: if you need live-maintained country data β€” current population, up-to-date memberships, professionally reviewed facts β€” REST Countries v5 is a real, maintained product and the 1,000 free monthly calls may be plenty for server-side use with caching. Host your own copy when the data you need is the stable 95% (names, codes, capitals, flags), when the request is coming from every visitor's browser (a country picker burns 1,000 calls fast), when you're teaching or following a tutorial, or when you never want a third-party deprecation to break your app again.

5. About this dataset

The dataset is derived from the open-source mledoze/countries project β€” the same community dataset the original REST Countries API was built on. It contains information from mledoze/countries, which is made available here under the Open Database License (ODbL) v1.0. Flattened for import: one record per country, arrays like capital reduced to their first value, languages/currencies joined into strings, borders kept as-is. Spot something wrong? It's your copy β€” PATCH it.

Create yours

The one-liner in section 1 is the whole setup β€” or open the dashboard and paste the dataset into the import panel. The same project can also mock any third-party API your app calls, serve weather- or news-shaped endpoints for the classic tutorial apps, add the matching currencies + exchange-rates or timezones datasets, or host any CSV as an API.