← Back to skills

Domain skill

rest-countries

Markdown synced from browser-harness domain skills.

Host
rest-countries
Files
1

Agent prompt

Use this skill

Copy this prompt into your coding agent to make it enable browser-harness domain skills and read this exact domain folder before automating.

Set up https://github.com/browser-use/browser-harness for me if it is not already installed. If setup is needed, read `install.md` first to install and connect it to my real browser. Then read `SKILL.md` for normal usage and always read `helpers.py` because that is where the browser-harness functions are.

Enable domain skills if they are not already enabled by setting `BH_DOMAIN_SKILLS=1` for browser-harness. Use the `rest-countries` domain skill from `agent-workspace/domain-skills/rest-countries/`. Read every markdown file for this domain before inventing an approach:
- agent-workspace/domain-skills/rest-countries/scraping.md

Use those domain-skill notes to complete my task for `rest-countries` in my real browser. When you open a setup, verification, or task tab, activate it so I can see the active browser tab.

Skill contents

What the agent will read

Scraping & Data Extraction

scraping.md

Source
  • https://restcountries.com — open JSON API for country data. Never use the browser. All data is reachable via httpget. No auth required, no API key.
  • Fetch all 250 countries in one call with a field filter — almost always the fastest approach.
  • Use the ?fields= query param to limit response size — essential when fetching all 250.
  • Use /alpha?codes= for fetching a known list of countries — always returns a list.
Show full markdown

https://restcountries.com — open JSON API for country data. Never use the browser. All data is reachable via http_get. No auth required, no API key.

Do this first

Fetch all 250 countries in one call with a field filter — almost always the fastest approach.

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/all?fields=name,cca2,capital,population,area,region")
countries = json.loads(data)
# countries is a list of 250 dicts — confirmed 2026-04-18

for c in countries:
    name       = c["name"]["common"]          # "Germany"
    official   = c["name"]["official"]        # "Federal Republic of Germany"
    code       = c["cca2"]                    # "DE"
    capital    = c["capital"][0] if c.get("capital") else None   # list — may be empty
    population = c["population"]              # 83491249
    area       = c["area"]                    # 357114.0 (km²)
    region     = c["region"]                  # "Europe"
    print(code, name, population)
# Confirmed output (first result varies — API returns unsorted):
# CI Ivory Coast 31719275

Use the ?fields= query param to limit response size — essential when fetching all 250.

Common workflows

Lookup a single country by code (ISO 3166-1 alpha-2 or alpha-3)

python
import json
from helpers import http_get

# Single code — returns a list (one element)
data = http_get("https://restcountries.com/v3.1/alpha/DE")
country = json.loads(data)[0]

# But: /alpha/CODE?fields=... returns a plain dict, not a list — watch for this
data2 = http_get("https://restcountries.com/v3.1/alpha/DE?fields=name,cca2,currencies,languages,flags")
country2 = json.loads(data2)          # dict, NOT list

name       = country2["name"]["common"]                             # "Germany"
currencies = country2["currencies"]                                 # {"EUR": {"name": "euro", "symbol": "€"}}
currency_codes = list(currencies.keys())                            # ["EUR"]
currency_name  = currencies["EUR"]["name"]                          # "euro"
languages  = country2["languages"]                                  # {"deu": "German"}
lang_names = list(languages.values())                               # ["German"]
flag_png   = country2["flags"]["png"]                               # "https://flagcdn.com/w320/de.png"
flag_svg   = country2["flags"]["svg"]                               # "https://flagcdn.com/de.svg"
flag_alt   = country2["flags"]["alt"]                               # description text

print(name, currency_codes, lang_names)
# Confirmed: Germany ['EUR'] ['German']

Batch lookup — multiple codes in one call

Use /alpha?codes= for fetching a known list of countries — always returns a list.

python
import json
from helpers import http_get

codes = ["US", "GB", "FR", "DE", "JP", "CN", "IN", "BR", "AU", "CA"]
data = http_get(f"https://restcountries.com/v3.1/alpha?codes={','.join(codes)}&fields=name,cca2,population")
countries = json.loads(data)
# Returns list, order NOT guaranteed to match input order
for c in countries:
    print(c["cca2"], c["name"]["common"], c["population"])
# Confirmed: 10 results, returned in arbitrary order

Search by name

python
import json
from helpers import http_get

# Partial match (default) — may return multiple results
data = http_get("https://restcountries.com/v3.1/name/united")
results = json.loads(data)
# Returns 7 countries: United States, UK, UAE, Tanzania, Mexico, ...

# Exact match — use fullText=true with the full common or official name
data2 = http_get("https://restcountries.com/v3.1/name/united%20kingdom?fullText=true")
results2 = json.loads(data2)
# Returns exactly 1 result: United Kingdom
print(results2[0]["name"]["common"])  # United Kingdom

Filter by region

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/region/europe?fields=name,cca2,population")
countries = json.loads(data)
# 53 European countries — confirmed

# Sort by population
ranked = sorted(countries, key=lambda x: x["population"], reverse=True)
for c in ranked[:5]:
    print(c["cca2"], c["name"]["common"], f"{c['population']:,}")
# Confirmed top 5: RU Russia, DE Germany, FR France, GB United Kingdom, IT Italy

Valid region values: africa, americas, asia, europe, oceania, antarctic

Filter by subregion

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/subregion/Western%20Europe?fields=name,cca2")
countries = json.loads(data)
print([c["cca2"] for c in countries])
# Confirmed: ['FR', 'NL', 'MC', 'DE', 'BE', 'LI', 'CH', 'LU']

Filter by language

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/lang/arabic")
countries = json.loads(data)
print(f"Arabic-speaking countries: {len(countries)}")
# Confirmed: 25 countries

# Language param is the language name (English), not the ISO 639-3 code
# Works: arabic, french, spanish, english, portuguese, german, russian, chinese

Filter by currency

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/currency/EUR")
countries = json.loads(data)
print(f"EUR countries: {len(countries)}")  # Confirmed: 36
names = [c["name"]["common"] for c in countries]
print(names[:5])

# Use ISO 4217 currency code (uppercase)

Filter by capital city

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/capital/berlin?fields=name,cca2,capital")
result = json.loads(data)
print(result[0]["name"]["common"], result[0]["capital"])
# Confirmed: Germany ['Berlin']
# Capital param is case-insensitive

Full country detail — all fields

python
import json
from helpers import http_get

data = http_get("https://restcountries.com/v3.1/alpha/US")
c = json.loads(data)[0]

# Available top-level keys (confirmed for US/DE):
# name, tld, cca2, ccn3, cca3, cioc, independent, status, unMember,
# currencies, idd, capital, altSpellings, region, subregion, languages,
# translations, latlng, landlocked, borders, area, demonyms, flag (emoji),
# maps, population, gini, fifa, car, timezones, continents, flags,
# coatOfArms, startOfWeek, capitalInfo, postalCode

print(c["idd"])          # {"root": "+1", "suffixes": ["201", "202", ...]}
print(c["car"]["side"])  # "right" or "left"
print(c["gini"])         # {"2018": 41.4}  — year keyed, may be absent
print(c["timezones"])    # list of UTC offset strings
print(c["borders"])      # list of cca3 codes for bordering countries
print(c["latlng"])       # [lat, lng] of geographic center

URL reference

EndpointPatternNotes
All countries/v3.1/allAlways add ?fields=
By code/v3.1/alpha/{code}cca2 or cca3; single code → list (no fields) or dict (with fields)
By codes/v3.1/alpha?codes=DE,FR,JPAlways returns list
By name/v3.1/name/{name}Partial; add ?fullText=true for exact match
By region/v3.1/region/{region}africa, americas, asia, europe, oceania, antarctic
By subregion/v3.1/subregion/{subregion}URL-encode spaces as %20
By language/v3.1/lang/{language}English language name
By currency/v3.1/currency/{code}ISO 4217 (EUR, USD, GBP)
By capital/v3.1/capital/{city}Case-insensitive

All endpoints accept ?fields=field1,field2,... to limit response payload.

Gotchas

  • name is a nested object, not a string. Use c["name"]["common"] for the familiar English name, c["name"]["official"] for the full official name. nativeName is a dict keyed by ISO 639-3 language code.

  • /alpha/CODE return type depends on whether ?fields= is present. Without ?fields=, returns a list (one element). With ?fields=..., returns a plain dict. Use json.loads(data)[0] for the no-fields case, json.loads(data) for the fields case. Using /alpha?codes=CODE always returns a list regardless.

  • currencies is a dict keyed by ISO 4217 code, not a list. c["currencies"]["EUR"]["name"]"euro", c["currencies"]["EUR"]["symbol"]"€". A country can have multiple currencies — iterate currencies.items().

  • languages is a dict keyed by ISO 639-3 code. c["languages"]["deu"]"German". Use list(c["languages"].values()) for a simple list of language names.

  • capital is a list and may be empty. Some territories (Antarctica, Bouvet Island, Macau, Heard Island) have no capital — c.get("capital") returns [], not None. Guard with c["capital"][0] if c.get("capital") else None. South Africa has 3 capitals.

  • gini is a dict keyed by year string, may be absent entirely. c["gini"]{"2016": 31.9}. Many small countries or territories have no gini data — always check c.get("gini").

  • borders uses cca3 codes, not cca2. c["borders"]["AUT", "BEL", ...]. Cross-reference with another /alpha?codes= call to resolve to names.

  • translations covers ~45 languages. Each entry: c["translations"]["deu"]{"official": "Bundesrepublik Deutschland", "common": "Deutschland"}. Useful for multilingual apps.

  • No rate limit headers, no documented rate limit. In practice the API handles rapid sequential calls fine. For bulk crawling hundreds of per-country requests, add a short sleep (time.sleep(0.5)) between calls to be polite.

  • 404 returns JSON, not HTML. {"message": "Not Found", "status": 404}. Wrap calls in try/except and check for this pattern when handling user-supplied country names or codes.

  • ?fields= is the key performance lever. The full all-countries payload without field filtering is ~1.5 MB. With ?fields=name,cca2,population it drops to ~50 KB. Always filter when you don't need all fields.