Short version: RestCountries v3.1 is deprecated, v5 needs an API key, and you'd like your app working again without signing up for anything. Here's the swap.
Endpoint mapping
countries.dev mirrors the endpoints people actually used. Drop the host and the version segment:
| What you want | RestCountries | countries.dev |
|---|---|---|
| All countries | /v3.1/all | /countries |
| By name | /v3.1/name/{name} | /name/{name} |
| By ISO code | /v3.1/alpha/{code} | /alpha/{code} |
| By currency | /v3.1/currency/{code} | /currency/{code} |
| By language | /v3.1/lang/{code} | /lang/{code} |
| By capital | /v3.1/capital/{city} | /capital/{city} |
| By region | /v3.1/region/{region} | /region/{region} |
The full list has a few more (subregion, calling code, top-level domain, numeric code).
The actual code change
Before — v5, with the key and header you now need:
const res = await fetch(
"https://api.restcountries.com/countries/v5/alpha/FR",
{ headers: { Authorization: `Bearer ${process.env.RC_KEY}` } }
);After:
const res = await fetch("https://countries.dev/alpha/FR");No env var, no header, no account. That's the migration.
Heads up: the response shape
countries.dev uses a flat shape — the v2-style one a lot of older code already expected — not v3.1's nested objects. So a couple of field reads change:
// RestCountries v3.1
country.name.common // "France"
country.capital[0] // "Paris"
// countries.dev
country.name // "France"
country.capital // "Paris"Currencies and languages come back as arrays of objects:
{
"name": "France",
"capital": "Paris",
"currencies": [{ "code": "EUR", "name": "Euro", "symbol": "€" }],
"languages": [{ "iso639_1": "fr", "iso639_2": "fra", "name": "French" }],
"flag": "🇫🇷"
}If you only read a few fields, request them and skip the rest:
curl "https://countries.dev/countries?fields=name,alpha2Code,flag"You can also sort, limit, and offset any list endpoint — handy now that you're not paginating around a quota.
One thing RestCountries can't do
While you're in here: /ip/{ip} geolocates an address and returns the whole country record, not just a two-letter code.
curl https://countries.dev/ip/8.8.8.8That's usually what "get the user's country" was really after.
Missing an endpoint you relied on? Let me know and I'll take a look.
Written by
Dov Azencot
At
Mon Jun 22 2026