Pythonic access to CIA World Factbook data
Project description
cia-world-factbook
Pythonic access to CIA World Factbook data for 256 countries and territories across 12 regions. Zero dependencies. Supports both attribute access (dot notation) and dictionary access with case-insensitive key lookup, tab completion, and built-in search.
Installation
pip install cia-world-factbook
Or with uv:
uv add cia-world-factbook
No external dependencies -- uses only the Python standard library.
Quick Start
from cia_world_factbook import us
us.geography.location.text
# 'North America, bordering both the North Atlantic Ocean and the North Pacific Ocean, between Canada and Mexico'
us.people_and_society.population.total.text
# '338,016,259 (2025 est.)'
us.government.capital.name.text
# 'Washington, DC'
us.economy.gdp_official_exchange_rate.text
# '$28.78 trillion (2024 est.)'
Two Ways to Access Data
Every piece of data supports both dot notation and bracket notation. You can mix them freely.
Attribute access (dot notation)
Keys are normalized to valid Python identifiers: lowercased, spaces/punctuation become underscores.
from cia_world_factbook import us
us.geography.location.text
us.people_and_society.population.total.text
us.economy.gdp_official_exchange_rate.text
Dictionary access (bracket notation)
Uses the original CIA Factbook key names. Case-insensitive.
us["Geography"]["Location"]["text"]
us["People and Society"]["Population"]["total"]["text"]
us["Economy"]["GDP (official exchange rate)"]["text"]
Mixed access
Combine both styles in the same expression:
us.government["Capital"]["name"].text
us["Geography"].location.text
Key normalization rules
| Original Key | Normalized | Rule |
|---|---|---|
People and Society |
people_and_society |
spaces to underscores |
Area - comparative |
area_comparative |
hyphens/spaces to underscores |
freshwater lake(s) |
freshwater_lake_s |
parentheses removed |
GDP - composition, by sector |
gdp_composition_by_sector |
punctuation removed |
0-14 years |
_0_14_years |
leading digit gets _ prefix |
Military & Security |
military_and_security |
& becomes and |
How key lookup works
When you access a key, the package tries three strategies in order:
- Exact match --
us["Geography"]finds"Geography"directly - Normalized match --
us.geographynormalizes to"geography", maps to"Geography" - Case-insensitive match --
us["geography"]matches"Geography"via lowercase comparison
This means us["Geography"], us["geography"], and us.geography all return the same data.
Loading Countries
Import directly
from cia_world_factbook import us, ca, gm, ja, br, fr
Countries are lazy-loaded -- no JSON is parsed until you first access a country. Subsequent accesses use a cache and are essentially free.
Load by name or code
from cia_world_factbook import load_country
# By 2-letter CIA code
us = load_country("us")
ja = load_country("ja")
# By friendly name
germany = load_country("germany")
australia = load_country("australia")
# By alias
usa = load_country("usa")
uk = load_country("united_kingdom")
Python keyword codes
The codes as (Australia), in (India), and is (Israel) are Python keywords and cannot be used with from ... import. Use load_country() or the friendly name instead:
# These WON'T work:
# from cia_world_factbook import as # SyntaxError
# from cia_world_factbook import in # SyntaxError
# These WILL work:
from cia_world_factbook import load_country
australia = load_country("as") # by code
australia = load_country("australia") # by name
from cia_world_factbook import australia # by friendly name import
Caching
Each country's JSON is parsed only once. All aliases for the same country share the same underlying data:
us1 = load_country("us")
us2 = load_country("usa")
us3 = load_country("united_states")
# us1.to_dict() == us2.to_dict() == us3.to_dict()
Discovering and Searching Countries
search(query) -- find countries by partial match
Searches country codes, friendly names, and aliases. Case-insensitive.
import cia_world_factbook
cia_world_factbook.search("korea")
# [('kn', 'north_korea', 'east-n-southeast-asia'),
# ('ks', 'south_korea', 'east-n-southeast-asia')]
cia_world_factbook.search("island")
# [('at', 'ashmore_and_cartier_islands', 'australia-oceania'),
# ('bp', 'solomon_islands', 'australia-oceania'),
# ('bq', 'navassa_island', 'central-america-n-caribbean'),
# ...]
cia_world_factbook.search("stan")
# [('af', 'afghanistan', 'south-asia'),
# ('kg', 'kyrgyzstan', 'central-asia'),
# ('kz', 'kazakhstan', 'central-asia'),
# ('pk', 'pakistan', 'south-asia'),
# ('ti', 'tajikistan', 'central-asia'),
# ('tx', 'turkmenistan', 'central-asia'),
# ('uz', 'uzbekistan', 'central-asia')]
Returns a list of (code, friendly_name, region) tuples.
info() -- print a full reference table
Prints a formatted table of all 256 countries to stdout, and also returns it as a string.
import cia_world_factbook
cia_world_factbook.info()
# Code Name Region
# ---------------------------------------------------------------------------
# ag algeria africa
# ao angola africa
# bn benin africa
# ... ... ...
list_countries() -- all 2-letter codes
from cia_world_factbook import list_countries
codes = list_countries()
# ['aa', 'ac', 'ae', 'af', 'ag', ..., 'zi']
len(codes)
# 256
list_regions() -- all 12 region names
from cia_world_factbook import list_regions
list_regions()
# ['africa', 'antarctica', 'australia-oceania', 'central-america-n-caribbean',
# 'central-asia', 'east-n-southeast-asia', 'europe', 'middle-east',
# 'north-america', 'south-america', 'south-asia', 'world']
Exploring Country Data
Data sections
Each country has up to 13 top-level sections:
from cia_world_factbook import us
list(us.keys())
# ['Introduction', 'Geography', 'People and Society', 'Environment',
# 'Government', 'Economy', 'Energy', 'Communications', 'Transportation',
# 'Military and Security', 'Space', 'Terrorism', 'Transnational Issues']
Not every country has all sections. Small territories may only have a few.
Drilling into a section
list(us.geography.keys())
# ['Location', 'Geographic coordinates', 'Map references', 'Area',
# 'Area - comparative', 'Land boundaries', 'Coastline', 'Maritime claims',
# 'Climate', 'Terrain', 'Elevation', 'Natural resources', 'Land use',
# 'Irrigated land', 'Major lakes (area sq km)', 'Major rivers (by length in km)',
# 'Major watersheds (area sq km)', 'Population distribution',
# 'Natural hazards', 'Geography - note']
len() -- how many keys at any level
len(us) # 13 top-level sections
len(us.geography) # 20 geography fields
len(us.economy) # number of economy fields
in operator -- check if a key exists
Works with both original and normalized key names:
"Geography" in us # True
"geography" in us # True (case-insensitive)
"people_and_society" in us # True (normalized)
"Nonexistent" in us # False
Iteration -- loop over keys
for section in us:
print(section)
# Introduction
# Geography
# People and Society
# ...
for key, value in us.geography.items():
print(f"{key}: {type(value)}")
# Location: <class 'cia_world_factbook._wrapper.FactbookDict'>
# Geographic coordinates: <class 'cia_world_factbook._wrapper.FactbookDict'>
# ...
keys(), values(), items()
These work like standard dict methods. keys() returns the original (un-normalized) key names:
us.keys() # dict_keys(['Introduction', 'Geography', 'People and Society', ...])
us.values() # [FactbookDict(...), FactbookDict(...), ...]
us.items() # [('Introduction', FactbookDict(...)), ('Geography', FactbookDict(...)), ...]
to_dict() -- get the raw underlying dict
Returns the original Python dictionary (not wrapped). Useful for serialization or passing to other libraries:
raw = us.geography.area.to_dict()
# {'total ': {'text': '9,833,517 sq km'}, 'land': {'text': '9,147,593 sq km'}, ...}
import json
json.dumps(raw, indent=2)
String Behavior
str() on leaf nodes returns the text directly
When a node contains only a text field (or text + note), str() returns just the text value. This makes print() work naturally:
print(us.geography.location)
# North America, bordering both the North Atlantic Ocean and the North Pacific Ocean, between Canada and Mexico
# Equivalent to:
print(us.geography.location.text)
str() on non-leaf nodes returns a summary
str(us.geography)
# "FactbookDict(['Location', 'Geographic coordinates', 'Map references', 'Area', 'Area - comparative'] ... +15 more)"
repr() shows available keys
Useful in the REPL for seeing what's inside a node:
>>> us.geography
FactbookDict(['Location', 'Geographic coordinates', 'Map references', 'Area', 'Area - comparative'] ... +15 more)
>>> us.geography.area
FactbookDict(['total ', 'land', 'water'])
Tab Completion (IPython / Jupyter)
dir() on any node returns normalized key names, which powers tab completion:
dir(us)
# ['communications', 'economy', 'energy', 'environment', 'geography',
# 'government', 'introduction', 'military_and_security',
# 'people_and_society', 'space', 'terrorism', 'transnational_issues',
# 'transportation']
dir(us.geography)
# ['area', 'area_comparative', 'climate', 'coastline', 'elevation', ...]
In IPython or Jupyter:
In [1]: from cia_world_factbook import us
In [2]: us.geo<TAB> # completes to us.geography
In [3]: us.geography.loc<TAB> # completes to us.geography.location
Tab completion also works at the module level:
In [1]: import cia_world_factbook
In [2]: cia_world_factbook.aus<TAB> # completes to cia_world_factbook.australia
Read-Only Data
All data is read-only. Attempting to modify any value raises an error:
us.geography = "nope"
# AttributeError: FactbookDict is read-only
Error Messages
Missing keys produce helpful error messages that list what's available:
us.geograpy # typo
# AttributeError: No key matching 'geograpy'. Available: Introduction, Geography, People and Society, ...
load_country("atlantis")
# ValueError: Unknown country 'atlantis'. Available: aa, ac, ae, af, ...
Performance
All data is bundled as JSON and loaded lazily. No database, no network calls, no external dependencies.
| Operation | Time |
|---|---|
| First load (single country, cold) | ~1ms |
| Cached load (subsequent access) | ~0.0001ms |
| Attribute traversal (4 levels deep) | ~0.04ms |
| Load ALL 256 countries | ~120ms |
| 1,000 queries across 5 countries | ~43ms |
| FactbookDict wrapper memory | 48 bytes |
Python is more than fast enough -- no native extensions needed.
Version
import cia_world_factbook
cia_world_factbook.__version__
# '0.1.0'
Complete API Reference
Module-level functions
| Function | Description |
|---|---|
load_country(name) |
Load a country by 2-letter code, friendly name, or alias. Returns a FactbookDict. |
search(query) |
Search countries by partial match. Returns list[tuple[code, name, region]]. |
info() |
Print a reference table of all countries. Also returns the table as a string. |
list_countries() |
Return sorted list of all 256 two-letter country codes. |
list_regions() |
Return sorted list of all 12 region names. |
Module-level attributes
| Attribute | Description |
|---|---|
__version__ |
Package version string (e.g., '0.1.0'). |
us, ca, gm, ... |
Lazy-loaded country data. Any registry key works as an import or attribute. |
FactbookDict -- the data wrapper
Every country and every nested node is a FactbookDict. It supports:
| Feature | Example | Description |
|---|---|---|
| Attribute access | us.geography |
Normalized key lookup with dot notation |
| Dictionary access | us["Geography"] |
Original or normalized key, case-insensitive |
str() |
str(us.geography.location) |
Returns text value for leaf nodes, repr for branches |
repr() |
repr(us.geography) |
Shows first 5 keys and count of remaining |
len() |
len(us) |
Number of keys at this level |
in |
"geography" in us |
Check if a key exists (case-insensitive) |
for key in obj |
for k in us: ... |
Iterate over original key names |
dir() |
dir(us) |
Normalized keys for tab completion |
keys() |
us.keys() |
Original key names (dict_keys) |
values() |
us.values() |
List of wrapped child values |
items() |
us.items() |
List of (original_key, wrapped_value) pairs |
to_dict() |
us.to_dict() |
Raw Python dict (unwrapped) |
| Read-only | us.x = 1 raises |
All data is immutable |
Data Source
Country data is sourced from factbook.json, a JSON extraction of the CIA World Factbook.
Country Reference
256 countries and territories across 12 regions. Use search() or info() to explore interactively, or expand a region below.
Africa (56)
| Code | Name | Aliases |
|---|---|---|
ag |
algeria | |
ao |
angola | |
bn |
benin | |
bc |
botswana | |
uv |
burkina_faso | |
by |
burundi | |
cv |
cabo_verde | |
cm |
cameroon | |
ct |
central_african_republic | |
cd |
chad | |
cn |
comoros | |
cg |
congo_democratic_republic | |
cf |
congo_republic | |
iv |
cote_d_ivoire | ivory_coast |
dj |
djibouti | |
eg |
egypt | |
ek |
equatorial_guinea | |
er |
eritrea | |
wz |
eswatini | |
et |
ethiopia | |
gb |
gabon | |
ga |
the_gambia | |
gh |
ghana | |
gv |
guinea | |
pu |
guinea_bissau | |
ke |
kenya | |
lt |
lesotho | |
li |
liberia | |
ly |
libya | |
ma |
madagascar | |
mi |
malawi | |
ml |
mali | |
mr |
mauritania | |
mp |
mauritius | |
mo |
morocco | |
mz |
mozambique | |
wa |
namibia | |
ng |
niger | |
ni |
nigeria | |
rw |
rwanda | |
sh |
saint_helena | |
tp |
sao_tome_and_principe | |
sg |
senegal | |
se |
seychelles | |
sl |
sierra_leone | |
so |
somalia | |
sf |
south_africa | |
od |
south_sudan | |
su |
sudan | |
tz |
tanzania | |
to |
togo | |
ts |
tunisia | |
ug |
uganda | |
wi |
western_sahara | |
za |
zambia | |
zi |
zimbabwe |
Antarctica (4)
| Code | Name |
|---|---|
ay |
antarctica |
bv |
bouvet_island |
fs |
french_southern_and_antarctic_lands |
hm |
heard_island_and_mcdonald_islands |
Australia & Oceania (30)
| Code | Name |
|---|---|
aq |
american_samoa |
as |
australia |
at |
ashmore_and_cartier_islands |
bp |
solomon_islands |
ck |
cocos_keeling_islands |
cq |
northern_mariana_islands |
cr |
coral_sea_islands |
cw |
cook_islands |
fj |
fiji |
fm |
micronesia |
fp |
french_polynesia |
gq |
guam |
kr |
kiribati |
kt |
christmas_island |
nc |
new_caledonia |
ne |
niue |
nf |
norfolk_island |
nh |
vanuatu |
nr |
nauru |
nz |
new_zealand |
pc |
pitcairn_islands |
ps |
palau |
rm |
marshall_islands |
tl |
tokelau |
tn |
tonga |
tv |
tuvalu |
um |
us_pacific_island_wildlife_refuges |
wf |
wallis_and_futuna |
wq |
wake_island |
ws |
samoa |
Central America & Caribbean (33)
| Code | Name |
|---|---|
aa |
aruba |
ac |
antigua_and_barbuda |
av |
anguilla |
bb |
barbados |
bf |
the_bahamas |
bh |
belize |
bq |
navassa_island |
cj |
cayman_islands |
cs |
costa_rica |
cu |
cuba |
do |
dominica |
dr |
dominican_republic |
es |
el_salvador |
gj |
grenada |
gt |
guatemala |
ha |
haiti |
ho |
honduras |
jm |
jamaica |
mh |
montserrat |
nn |
sint_maarten |
nu |
nicaragua |
pm |
panama |
rn |
saint_martin |
rq |
puerto_rico |
sc |
saint_kitts_and_nevis |
st |
saint_lucia |
tb |
saint_barthelemy |
td |
trinidad_and_tobago |
tk |
turks_and_caicos_islands |
uc |
curacao |
vc |
saint_vincent_and_the_grenadines |
vi |
british_virgin_islands |
vq |
virgin_islands |
Central Asia (6)
| Code | Name |
|---|---|
kg |
kyrgyzstan |
kz |
kazakhstan |
rs |
russia |
ti |
tajikistan |
tx |
turkmenistan |
uz |
uzbekistan |
East & Southeast Asia (22)
| Code | Name | Aliases |
|---|---|---|
bm |
burma | myanmar |
bx |
brunei | |
cb |
cambodia | |
ch |
china | peoples_republic_of_china |
hk |
hong_kong | |
id |
indonesia | |
ja |
japan | |
kn |
north_korea | |
ks |
south_korea | |
la |
laos | |
mc |
macau | |
mg |
mongolia | |
my |
malaysia | |
pf |
paracel_islands | |
pg |
spratly_islands | |
pp |
papua_new_guinea | |
rp |
philippines | |
sn |
singapore | |
th |
thailand | |
tt |
timor_leste | |
tw |
taiwan | |
vm |
vietnam |
Europe (55)
| Code | Name | Aliases |
|---|---|---|
al |
albania | |
an |
andorra | |
au |
austria | |
ax |
akrotiri | |
be |
belgium | |
bk |
bosnia_and_herzegovina | |
bo |
belarus | |
bu |
bulgaria | |
cy |
cyprus | |
da |
denmark | |
dx |
dhekelia | |
ee |
european_union | |
ei |
ireland | |
en |
estonia | |
ez |
czechia | |
fi |
finland | |
fo |
faroe_islands | |
fr |
france | |
gi |
gibraltar | |
gk |
guernsey | |
gm |
germany | |
gr |
greece | |
hr |
croatia | |
hu |
hungary | |
ic |
iceland | |
im |
isle_of_man | |
it |
italy | |
je |
jersey | |
jn |
jan_mayen | |
kv |
kosovo | |
lg |
latvia | |
lh |
lithuania | |
lo |
slovakia | |
ls |
liechtenstein | |
lu |
luxembourg | |
md |
moldova | |
mj |
montenegro | |
mk |
north_macedonia | |
mn |
monaco | |
mt |
malta | |
nl |
netherlands | |
no |
norway | |
pl |
poland | |
po |
portugal | |
ri |
serbia | |
ro |
romania | |
si |
slovenia | |
sm |
san_marino | |
sp |
spain | |
sv |
svalbard | |
sw |
sweden | |
sz |
switzerland | |
uk |
united_kingdom | england, great_britain |
up |
ukraine | |
vt |
holy_see | vatican |
Middle East (19)
| Code | Name | Aliases |
|---|---|---|
ae |
united_arab_emirates | uae |
aj |
azerbaijan | |
am |
armenia | |
ba |
bahrain | |
gg |
georgia | |
gz |
gaza_strip | |
ir |
iran | |
is |
israel | |
iz |
iraq | |
jo |
jordan | |
ku |
kuwait | |
le |
lebanon | |
mu |
oman | |
qa |
qatar | |
sa |
saudi_arabia | |
sy |
syria | |
tu |
turkey | |
we |
west_bank | |
ym |
yemen |
North America (7)
| Code | Name | Aliases |
|---|---|---|
bd |
bermuda | |
ca |
canada | |
gl |
greenland | |
ip |
clipperton_island | |
mx |
mexico | |
sb |
saint_pierre_and_miquelon | |
us |
united_states | usa, america, united_states_of_america |
South America (14)
| Code | Name |
|---|---|
ar |
argentina |
bl |
bolivia |
br |
brazil |
ci |
chile |
co |
colombia |
ec |
ecuador |
fk |
falkland_islands |
gy |
guyana |
ns |
suriname |
pa |
paraguay |
pe |
peru |
sx |
south_georgia_and_south_sandwich_islands |
uy |
uruguay |
ve |
venezuela |
South Asia (9)
| Code | Name |
|---|---|
af |
afghanistan |
bg |
bangladesh |
bt |
bhutan |
ce |
sri_lanka |
in |
india |
io |
british_indian_ocean_territory |
mv |
maldives |
np |
nepal |
pk |
pakistan |
World (1)
| Code | Name |
|---|---|
xx |
world |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cia_world_factbook-0.1.1.tar.gz.
File metadata
- Download URL: cia_world_factbook-0.1.1.tar.gz
- Upload date:
- Size: 2.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36a865ee1ae25c0596c1ef0c5301a7e48967396f12b3225318040c0e13bd6e89
|
|
| MD5 |
b7679f016f8cdc4af3b66ee24beed991
|
|
| BLAKE2b-256 |
0ed1578365707b50742feda0ca7cffd9bf6c1834717b44997a7cb7c21e7d36a9
|
File details
Details for the file cia_world_factbook-0.1.1-py3-none-any.whl.
File metadata
- Download URL: cia_world_factbook-0.1.1-py3-none-any.whl
- Upload date:
- Size: 2.9 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab067af5a100e5b249b02a4b148adf538580e6e60a7f2917f3040c3d35f42a6b
|
|
| MD5 |
4ed8fed4534e1b9526467844c21bbdc3
|
|
| BLAKE2b-256 |
e0a0bd671c89f10af1b6c9575842d63df837e7db19569858e2be3d75c08ad0ff
|