One pip install. Every geospatial dataset. Any country on Earth.
Specialising in African communities, powered entirely by open data.
GeoAfrica is a unified Python SDK for geospatial data access, built and maintained by Merczcord Technologies Ltd.
It aggregates 10+ authoritative open-data sources into a single, developer-friendly interface, no complex API wrangling, no data format juggling.
Whether you're mapping health facilities in Nigeria, tracking active wildfires in Ethiopia, analysing population density in Kenya, or querying road networks across West Africa, one import is all you need.
import geoafrica
# That's it. Every dataset in Africa and the world, at your fingertips.| Module | What it does | Data Source |
|---|---|---|
geoafrica.boundaries |
Admin boundaries at any level (0–3) | GADM, HDX |
geoafrica.population |
Population grids & statistics | WorldPop, SEDAC |
geoafrica.osm |
Any OSM feature — hospitals, roads, schools | OpenStreetMap / Overpass |
geoafrica.satellite |
Sentinel-2, Landsat, Digital Earth Africa STAC | DE Africa, Earth Search |
geoafrica.climate |
Rainfall & temperature rasters | CHIRPS, ERA5 |
geoafrica.health |
Health facilities worldwide | HealthSites.io, WHO |
geoafrica.fire |
Near real-time & historical fire detections | NASA FIRMS |
geoafrica.elevation |
DEM — SRTM, Copernicus, AW3D30, NASADEM | OpenTopography |
geoafrica.humanitarian |
Crisis, displacement, flood datasets | UN OCHA HDX |
geoafrica.roads |
Road networks & density stats | OpenStreetMap |
geoafrica.viz |
Interactive Folium maps, choropleths | - |
geoafrica.analysis |
Clip, buffer, zonal stats, proximity | - |
pip install geoafricaFor satellite imagery support:
pip install geoafrica[satellite]For climate ERA5 support:
pip install geoafrica[climate]Full install (everything):
pip install geoafrica[full]Python 3.9+ required. Works on Windows, macOS, and Linux.
Most modules work without any API key. A few providers require a free registration:
| Provider | Required For | Register |
|---|---|---|
| NASA FIRMS | geoafrica.fire |
firms.modaps.eosdis.nasa.gov |
| OpenTopography | geoafrica.elevation (large areas) |
portal.opentopography.org |
| Copernicus CDS | ERA5 climate data | cds.climate.copernicus.eu |
Set your keys via CLI:
geoafrica config set GEOAFRICA_FIRMS_KEY your_key_hereOr via environment variables:
export GEOAFRICA_FIRMS_KEY=your_key_hereOr in Python:
import geoafrica
geoafrica.configure(nasa_firms_key="your_key_here")import matplotlib.pyplot as plt
from geoafrica import boundaries, viz
# 1. Get Country Outline
nigeria = boundaries.get_country("Nigeria")
# Print the first few rows
print("--- NIGERIA BOUNDARY DATA ---")
print(nigeria.head())
# Static Plot (Matplotlib)
nigeria.plot(color='lightgreen', edgecolor='black', figsize=(6, 6))
plt.title("Nigeria - Country Outline")
plt.show()
# 2. Get States / Provinces
states = boundaries.get_admin("Nigeria", level=1)
print(f"\nTotal states found: {len(states)}")
# 3. Interactive Web Maps (Folium)
# Generate a pan/zoomable interactive map
interactive_map = viz.quick_map(states)
# interactive_map.save("states_map.html")
# In Jupyter/Colab, simply place 'interactive_map' on the last line to view inline:
# interactive_map
# 4. Districts & Bounding Boxes
districts = boundaries.get_admin("Kenya", level=2)
ghana = boundaries.get_by_iso("GH", level=1)
bbox = boundaries.get_bbox("Ethiopia") # [33.0, 3.4, 47.9, 14.9]
# 5. List supported countries
all_countries = boundaries.list_countries()
africa_only = boundaries.list_countries(region="Africa")from geoafrica import population
import matplotlib.pyplot as plt
# 1km population grid (WorldPop)
pop_grid = population.get_grid("Nigeria", year=2020, resolution=1000)
print(f"Total pop: {int(pop_grid.where(pop_grid > 0).sum().values):,}")
# View the population density raster
pop_grid.plot(cmap="hot", figsize=(7, 7))
plt.title("Nigeria - Population Density")
plt.show()
# Admin-level statistics
stats = population.get_stats("Lagos", country="Nigeria", level=1)
# Returns DataFrame: admin_name, population, area_km2, density_per_km2
# Available data years
years = population.available_years("Ghana")from geoafrica import osm, viz
import matplotlib.pyplot as plt
# Hospitals in Lagos
hospitals = osm.get_amenity("Lagos, Nigeria", amenity="hospital")
# Print top 5 results
print(hospitals[['name', 'amenity', 'geometry']].head())
# View interactively (in Jupyter)
# viz.quick_map(hospitals, color="blue")
# Schools across Ghana
schools = osm.get_amenity("Ghana", amenity="school")
# Primary roads in Nairobi
roads = osm.get_roads("Nairobi", road_type="primary")
# Buildings in a city
buildings = osm.get_buildings("Kigali")
# Custom tags — any OSM feature
water_sources = osm.get_features(
"Ethiopia",
tags={"amenity": "drinking_water"}
)
# Search within a bounding box
markets = osm.get_features_bbox(
bbox=[3.0, 6.3, 3.5, 6.7],
tags={"amenity": "marketplace"}
)from geoafrica import climate
import matplotlib.pyplot as plt
# Annual rainfall for Ethiopia
rain_2023 = climate.get_rainfall("Ethiopia", year=2023)
# View the climate raster
rain_2023.plot(cmap="Blues", figsize=(8, 6))
plt.title("Ethiopia - 2023 Rainfall (mm)")
plt.show()
# Monthly rainfall (July 2022)
rain_july = climate.get_rainfall("Nigeria", year=2022, month=7)
# Monthly time series as DataFrame
monthly = climate.monthly_series("Ghana", year=2023)
# month | month_name | mean_rainfall_mm | max_rainfall_mm
# Rainfall anomaly vs 1981–2010 baseline
anomaly = climate.rainfall_anomaly("Senegal", year=2022)from geoafrica import fire, viz
import matplotlib.pyplot as plt
# Active fires in Nigeria (last 7 days)
fires = fire.get_country("Nigeria", days=7)
print(f"Total active fires: {len(fires)}")
# Plot static map
fires.plot(color='red', markersize=5, figsize=(6,6))
plt.title("Active Fires (Last 7 Days)")
plt.show()
# View interactive Heatmap
# heatmap = viz.fire_map(fires, country="Nigeria")
# Fires in West Africa bounding box
west_africa = fire.get_active(bbox=[-18, 4, 16, 20], days=3)
# Historical fire data
hist = fire.get_historical(
"Democratic Republic of Congo",
start="2023-01-01",
end="2023-12-31"
)
# Quick summary
summary = fire.summary(fires, by="acq_date")from geoafrica import elevation
import matplotlib.pyplot as plt
# SRTM 30m DEM for Rwanda
dem = elevation.get_dem("Rwanda", source="SRTMGL1")
# Visualize terrain raster
dem.plot(cmap="terrain", figsize=(8, 8))
plt.title("Rwanda - Digital Elevation Model")
plt.show()
# Copernicus 30m DEM
dem_cop = elevation.get_dem("Kenya", source="COP30")
# Elevation profile between two points
profile = elevation.terrain_profile(
start=(36.8, 3.8), # (lon, lat) near Addis Ababa
end=(38.7, 6.1),
num_points=200,
)
profile.plot(x="distance_km", y="elevation_m")
# Slope and aspect
slope, aspect = elevation.compute_slope_aspect(dem)
# List all available DEM sources
elevation.list_sources()from geoafrica import health, viz
# All hospitals in Nigeria
hospitals = health.get_facilities("Nigeria", facility_type="hospital")
print(hospitals[['name', 'facility_type']].head())
# Interactively view hospital locations
# map_hospitals = viz.quick_map(hospitals, color="red")
# Clinics in Ghana
clinics = health.get_facilities("Ghana", facility_type="clinic")
# Nearest 3 hospitals to a point (e.g. Lagos Island)
nearest = health.nearest_to(lat=6.45, lon=3.39, country="Nigeria", n=3)
# Facility count per state
counts = health.count_by_admin("Kenya", level=1)from geoafrica import humanitarian
# Search datasets
results = humanitarian.search("Nigeria flood 2024", rows=10)
# Get all resources in a dataset
resources = humanitarian.get_dataset("cod-ab-nga")
# Download shapefiles
files = humanitarian.download_dataset("cod-ab-nga", resource_format="SHP")
# Country-specific data
nigeria_data = humanitarian.get_country_datasets("Nigeria", data_type="displacement")
# Load as GeoDataFrame directly
gdf = humanitarian.load_geospatial("cod-ab-nga")from geoafrica import satellite
# Search Sentinel-2 scenes
items = satellite.search(
collection="sentinel-2-l2a",
country="Rwanda",
date_range="2023-06-01/2023-09-30",
max_cloud_cover=15,
limit=5,
)
print(f"Found {len(items)} scenes")
# List all collections from Digital Earth Africa
deafrica_cols = satellite.deafrica_products()
# Load RGB composite
import matplotlib.pyplot as plt
rgb = satellite.load_rgb(items[0])
# Plot the RGB composite satellite image
rgb.plot.imshow(figsize=(8, 8))
plt.title("Sentinel-2 RGB Composite")
plt.show()from geoafrica.analysis import spatial, zonal_stats, proximity
# Clip hospitals to Lagos state
lagos = boundaries.get_admin("Lagos", country="Nigeria", level=1)
lagos_hospitals = spatial.clip(hospitals, lagos)
# Buffer schools by 2km (service area)
school_zones = spatial.buffer_km(schools, km=2)
# Population within admin units (zonal stats)
pop_stats = zonal_stats.compute(pop_grid, states, stats=["mean", "sum", "max"])
# Find nearest facility for each village
result = proximity.nearest_facility(villages, hospitals)
# Service coverage — % of population within 5km of any hospital
coverage = proximity.service_coverage(hospitals, pop_grid, radius_km=5)
print(f"Coverage: {coverage['coverage_pct']}%")from geoafrica import viz
# Quick interactive map
m = viz.quick_map(hospitals, color="#E91E63", tooltip_cols=["name", "facility_type"])
m.save("hospitals.html")
# Choropleth map
m = viz.choropleth(
states.merge(pop_stats, on="NAME_1"),
column="sum",
title="Nigeria — Population by State",
)
m.save("population_choropleth.html")
# Multi-layer map
m = viz.quick_map(states)
viz.add_layer(m, hospitals, name="Hospitals", color="#E53935")
viz.add_layer(m, schools, name="Schools", color="#43A047")
m.save("multi_layer.html")
# Fire heatmap
fires_map = viz.fire_map(fires, country="Nigeria")
fires_map.save("fires.html")from geoafrica.io import readers, writers
# Read any geospatial file
gdf = readers.read("data/nigeria.geojson")
gdf = readers.read("s3://my-bucket/data.gpkg", layer="roads")
# Read CSV with lat/lon columns
gdf = readers.read_csv_geo("hospitals.csv", lat_col="lat", lon_col="lng")
# Write to multiple formats
writers.to_geojson(hospitals, "hospitals.geojson")
writers.to_shapefile(hospitals, "hospitals.shp")
writers.to_geopackage(hospitals, "data.gpkg", layer="hospitals")
writers.to_csv(hospitals, "hospitals.csv")
writers.to_geoparquet(hospitals, "hospitals.parquet")# Show version and API key status
geoafrica info
# Download boundaries
geoafrica boundaries nigeria --level 1 --output states.geojson
geoafrica boundaries ghana --level 2 --source hdx --output gh_districts.gpkg
# OpenStreetMap queries
geoafrica osm facilities --location "Kenya" --type hospital --output ke_hospitals.geojson
geoafrica osm roads --location "Lagos, Nigeria" --type primary
# Fire detections
geoafrica fire active --country Nigeria --days 7 --output fires.geojson
geoafrica fire active --bbox "-18,4,30,20" --days 3
# Elevation
geoafrica elevation dem --country Rwanda --source COP30 --output rwanda.tif
geoafrica elevation sources
# Configuration
geoafrica config set GEOAFRICA_FIRMS_KEY your_nasa_key
geoafrica config show
# List countries
geoafrica countries --region africaGeoAfrica has built-in support for all 54 African nations plus major countries worldwide. Use any of the following identifier formats:
# These all work
boundaries.get_country("Nigeria")
boundaries.get_country("NG") # ISO-2
boundaries.get_country("NGA") # ISO-3
boundaries.get_country("DRC") # Common abbreviationgeoafrica/
├── core/ # Config, HTTP session, exceptions
├── datasets/ # 10 data modules (boundaries, population, osm, ...)
├── analysis/ # Spatial ops, zonal stats, proximity
├── io/ # Universal readers & writers
└── viz/ # Folium interactive maps
Design principles:
- Plug-and-play — zero config for most modules
- Smart caching — downloads cached locally to avoid re-fetching
- Retry logic — automatic retry with exponential backoff
- Rate limiting — per-host rate limiting to respect API policies
- Standard outputs — all vector data returns
GeoDataFrame, rasters returnxarray.DataArray
GeoAfrica aggregates open data. Please attribute the original providers:
| Source | License | Citation |
|---|---|---|
| GADM | CC BY 4.0 (non-commercial) | gadm.org |
| WorldPop | CC BY 4.0 | worldpop.org |
| OpenStreetMap | ODbL | © OpenStreetMap contributors |
| NASA FIRMS | Open | NASA EOSDIS FIRMS |
| CHIRPS | Open | Funk et al., 2015 |
| HealthSites.io | CC BY 4.0 | healthsites.io |
| HDX / UN OCHA | CC BY-IGO 3.0 | data.humdata.org |
| OpenTopography | CC BY 4.0 | opentopography.org |
Contributions are welcome! To add a new data module:
- Create
src/geoafrica/datasets/your_module.py - Follow the existing module pattern (returns
GeoDataFrameorDataArray) - Add unit tests in
tests/test_your_module.py - Add to
src/geoafrica/datasets/__init__.py - Submit a PR
MIT License — see LICENSE.
GeoAfrica is a product of Merczcord Technologies Ltd., a technology company focused on building data infrastructure and geospatial intelligence tools for African communities and beyond.
- Website: merczcord.com
- Contact: info@merczcord.com
- GitHub: github.com/Mercy14846/Geo-API