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
- 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.
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)
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.
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
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
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
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
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
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
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
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
| Endpoint | Pattern | Notes |
|---|---|---|
| All countries | /v3.1/all | Always 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,JP | Always 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
-
nameis a nested object, not a string. Usec["name"]["common"]for the familiar English name,c["name"]["official"]for the full official name.nativeNameis a dict keyed by ISO 639-3 language code. -
/alpha/CODEreturn type depends on whether?fields=is present. Without?fields=, returns a list (one element). With?fields=..., returns a plain dict. Usejson.loads(data)[0]for the no-fields case,json.loads(data)for the fields case. Using/alpha?codes=CODEalways returns a list regardless. -
currenciesis 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 — iteratecurrencies.items(). -
languagesis a dict keyed by ISO 639-3 code.c["languages"]["deu"]→"German". Uselist(c["languages"].values())for a simple list of language names. -
capitalis a list and may be empty. Some territories (Antarctica, Bouvet Island, Macau, Heard Island) have no capital —c.get("capital")returns[], notNone. Guard withc["capital"][0] if c.get("capital") else None. South Africa has 3 capitals. -
giniis 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 checkc.get("gini"). -
bordersuses cca3 codes, not cca2.c["borders"]→["AUT", "BEL", ...]. Cross-reference with another/alpha?codes=call to resolve to names. -
translationscovers ~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,populationit drops to ~50 KB. Always filter when you don't need all fields.