import {ms, msStyle} from "/assets/js/ms-plot.js"
sources = [
{n: 1, method: "Python package", name: "Kaggle Datasets", dom: "π§ͺ ML practice", what: "Hundreds of thousands of community datasets, many with notebooks", how: "Python package / CLI", key: "Free account token", fmt: "CSV, Parquet, images", url: "https://www.kaggle.com/datasets"},
{n: 2, method: "Python package", name: "UCI ML Repository", dom: "π§ͺ ML practice", what: "Classic, well-documented ML benchmark datasets", how: "Python package", key: "None", fmt: "CSV via pandas", url: "https://archive.ics.uci.edu/"},
{n: 3, method: "Python package", name: "OpenML", dom: "π§ͺ ML practice", what: "Datasets plus tasks and benchmark results", how: "Python package", key: "None", fmt: "pandas via scikit-learn", url: "https://www.openml.org/"},
{n: 4, method: "Python package", name: "Hugging Face Datasets", dom: "π§ͺ ML practice", what: "Over a million datasets: text, images, audio, tabular", how: "Python package", key: "None for public", fmt: "Parquet, Arrow, CSV, JSON", url: "https://huggingface.co/datasets"},
{n: 5, method: "Search", name: "Google Dataset Search", dom: "π Discovery", what: "A search engine that finds datasets across the web", how: "Search, then download", key: "None", fmt: "Varies", url: "https://datasetsearch.research.google.com/"},
{n: 6, method: "Download", name: "Data.gov", dom: "ποΈ Government", what: "U.S. federal open-data catalogue, hundreds of thousands of datasets", how: "Download / catalogue API", key: "None", fmt: "CSV, JSON, APIs", url: "https://data.gov/"},
{n: 7, method: "REST API", name: "U.S. Census Bureau", dom: "ποΈ Government", what: "Population, income, housing, business statistics", how: "REST API", key: "Free key recommended", fmt: "JSON", url: "https://www.census.gov/data/developers.html"},
{n: 8, method: "Download", name: "FRED (St. Louis Fed)", dom: "πΉ Economics", what: "Hundreds of thousands of economic time series", how: "CSV link / REST API", key: "Free key for API", fmt: "CSV, JSON", url: "https://fred.stlouisfed.org/docs/api/fred/"},
{n: 9, method: "REST API", name: "World Bank Open Data", dom: "πΉ Economics", what: "Development indicators for every country since 1960", how: "REST API", key: "None", fmt: "JSON, XML", url: "https://datahelpdesk.worldbank.org/knowledgebase/articles/898581-api-basic-call-structures"},
{n: 10, method: "REST API", name: "Eurostat", dom: "πΉ Economics", what: "Official statistics for the EU", how: "REST API / bulk TSV", key: "None", fmt: "JSON-stat, TSV", url: "https://ec.europa.eu/eurostat/data/database"},
{n: 11, method: "Download", name: "Our World in Data", dom: "π Society & health", what: "Clean, documented global data behind thousands of charts", how: "CSV link", key: "None", fmt: "CSV", url: "https://ourworldindata.org/"},
{n: 12, method: "REST API", name: "WHO Global Health Observatory", dom: "π Society & health", what: "Health indicators by country and year", how: "OData REST API", key: "None", fmt: "JSON, XML", url: "https://www.who.int/data/gho/info/gho-odata-api"},
{n: 13, method: "REST API", name: "NOAA Climate Data Online", dom: "π¦οΈ Climate & earth", what: "Historical weather and climate observations", how: "REST API", key: "Free token", fmt: "JSON, CSV", url: "https://www.ncei.noaa.gov/cdo-web/webservices/v2"},
{n: 14, method: "Python package", name: "NASA Earthdata", dom: "π¦οΈ Climate & earth", what: "Satellite and earth-science data", how: "Python package", key: "Free Earthdata login", fmt: "NetCDF, HDF, GeoTIFF", url: "https://www.earthdata.nasa.gov/"},
{n: 15, method: "REST API", name: "OpenStreetMap (Overpass)", dom: "πΊοΈ Geospatial", what: "Crowd-sourced map data: roads, shops, buildings", how: "REST API", key: "None", fmt: "JSON, XML", url: "https://wiki.openstreetmap.org/wiki/Overpass_API"},
{n: 16, method: "Download", name: "NYC TLC Trip Records", dom: "π Mobility", what: "Billions of taxi and ride-hail trips, by month", how: "File download", key: "None", fmt: "Parquet", url: "https://www.nyc.gov/site/tlc/about/tlc-trip-record-data.page"},
{n: 17, method: "REST API", name: "SEC EDGAR", dom: "πΉ Economics", what: "Company filings and XBRL financial data", how: "REST API", key: "None (User-Agent header required)", fmt: "JSON", url: "https://www.sec.gov/search-filings/edgar-application-programming-interfaces"},
{n: 18, method: "Cloud bucket", name: "AWS Open Data Registry", dom: "βοΈ Big data", what: "Large public datasets stored in S3", how: "Cloud bucket", key: "None for most", fmt: "Parquet, Zarr, CSV, imagery", url: "https://registry.opendata.aws/"},
{n: 19, method: "SQL", name: "Google BigQuery public datasets", dom: "βοΈ Big data", what: "Public datasets you can query with SQL", how: "SQL", key: "Google Cloud project", fmt: "Tables", url: "https://cloud.google.com/bigquery/public-data"},
{n: 20, method: "Cloud bucket", name: "Common Crawl", dom: "βοΈ Big data", what: "Petabytes of open web-crawl data for NLP", how: "Cloud bucket / HTTP", key: "None", fmt: "WARC, WAT, WET", url: "https://commoncrawl.org/get-started"}
]
viewof dom = Inputs.select(["All domains", ...new Set(sources.map(d => d.dom))], {label: "π·οΈ Domain"})
viewof noKey = Inputs.toggle({label: "π Only sources needing no key or account", value: false})20 Famous Open Data Sources for Analytics, and How to Extract Data ποΈ
Resources
Datasets
Open Data
APIs
The twenty best-known free data sources, from Kaggle and UCI to FRED, the World Bank, NASA and SEC EDGAR, with a filterable catalogue, extraction code for each access method and a simulated end-to-end pipeline.
Good practice data is the fuel of every project. The twenty sources below are free, famous and reliable. Some give you a CSV with one click; others need an API call, a Python package or a SQL query. This guide shows what each source is good for and exactly how to pull data from it. π
Tipπ― What you will get
- ποΈ A filterable catalogue of 20 open data sources
- π§ A decision flow for choosing the right extraction method
- π» Copy-ready extraction code for downloads, APIs, Python packages, SQL and cloud buckets
- π An animated extract β clean β store pipeline and a worked, simulated example
- βοΈ Notes on licences, rate limits and good manners
Noteπ The Resources hub
π§ Overview: where to find resources Β· π€οΈ Learning paths Β· π Cheat sheets Β· π Glossary Β· ποΈ 20 open data sources Β· π Paper notes (coming soon)
ποΈ The catalogue
How do you get the data out? The chart counts the main access method for each source.
Noteπ Note
The FRED CSV link works without a key, for example fredgraph.csv?id=UNRATE (FRED); the full API needs a free key (FRED API docs).
π§ Which extraction method?
flowchart TD
A["β What does the source offer?"] --> B{"A download link?"}
B -- yes --> C["π₯ pandas.read_csv / read_parquet<br/>straight from the URL"]
B -- no --> D{"A Python package?"}
D -- yes --> E["π¦ ucimlrepo, datasets,<br/>fetch_openml, earthaccess, kaggle"]
D -- no --> F{"A REST API?"}
F -- yes --> G["π requests + JSON<br/>pagination, keys, rate limits"]
F -- no --> H{"A SQL warehouse<br/>or cloud bucket?"}
H -- SQL --> I["ποΈ BigQuery client"]
H -- bucket --> J["βοΈ S3 with --no-sign-request"]
π» Extraction recipes
Each tab is a working pattern. Replace dataset codes and keys with your own. Keys belong in environment variables, never in notebooks you share.
import pandas as pd
# Our World in Data: every chart has a CSV
le = pd.read_csv(
"https://ourworldindata.org/grapher/life-expectancy.csv")
# FRED: one series, no key needed
unrate = pd.read_csv(
"https://fred.stlouisfed.org/graph/fredgraph.csv?id=UNRATE",
parse_dates=["observation_date"])
# NYC TLC: copy a monthly Parquet link from the TLC page
trips = pd.read_parquet("<paste-yellow-tripdata-link>.parquet")# UCI repository
from ucimlrepo import fetch_ucirepo # pip install ucimlrepo
wine = fetch_ucirepo(id=109)
X, y = wine.data.features, wine.data.targets
# OpenML through scikit-learn
from sklearn.datasets import fetch_openml
titanic = fetch_openml("titanic", version=1, as_frame=True).frame
# Hugging Face
from datasets import load_dataset # pip install datasets
imdb = load_dataset("imdb", split="train").to_pandas()
# Kaggle (token in ~/.kaggle/kaggle.json)
# kaggle datasets download -d blastchar/telco-customer-churn --unzipimport os, requests, pandas as pd
# World Bank: no key; JSON when format=json
url = ("https://api.worldbank.org/v2/country/US;IN;BR"
"/indicator/NY.GDP.MKTP.CD")
page = requests.get(url, params={"format": "json",
"per_page": 500}).json()
meta, rows = page # [paging info, records]
gdp = pd.json_normalize(rows)[["country.value", "date", "value"]]
# FRED API: free key in an environment variable
obs = requests.get(
"https://api.stlouisfed.org/fred/series/observations",
params={"series_id": "CPIAUCSL", "file_type": "json",
"api_key": os.environ["FRED_API_KEY"]}).json()
cpi = pd.DataFrame(obs["observations"])
# SEC EDGAR: no key, but identify yourself
hdr = {"User-Agent": "Your Name your.email@example.com"}
apple = requests.get(
"https://data.sec.gov/submissions/CIK0000320193.json",
headers=hdr).json()import requests, pandas as pd
# OpenStreetMap Overpass: cafΓ©s in central Austin
query = """
[out:json][timeout:25];
node["amenity"="cafe"](30.25,-97.76,30.29,-97.72);
out;
"""
r = requests.post("https://overpass-api.de/api/interpreter",
data={"data": query}).json()
cafes = pd.DataFrame([{"name": e["tags"].get("name"),
"lat": e["lat"], "lon": e["lon"]}
for e in r["elements"]])# pip install google-cloud-bigquery ; gcloud auth application-default login
from google.cloud import bigquery
client = bigquery.Client(project="your-project-id")
sql = """
SELECT name, SUM(number) AS babies
FROM `bigquery-public-data.usa_names.usa_1910_current`
WHERE year >= 2000
GROUP BY name ORDER BY babies DESC LIMIT 10
"""
top_names = client.query(sql).to_dataframe()# AWS Open Data and Common Crawl allow anonymous access
aws s3 ls s3://commoncrawl/crawl-data/ --no-sign-request
# copy one file to your machine
aws s3 cp s3://<bucket>/<path>/file.parquet . --no-sign-requestBigQuery gives every project the first 1 TB of queries per month free, and Google pays to store the public datasets (Google Cloud). NOAAβs API needs a token in the request header and allows 5 requests per second and 10,000 per day (NOAA).
π The extraction pipeline, animated
Real projects wrap extraction in a small pipeline so it can be re-run safely. Press play and follow a batch of records.
π§ͺ Worked example: cleaning API data (simulated)
APIs rarely return a tidy table. Below we simulate a World Bank-style JSON response for five fictional countries, with typical problems: nested fields, values as strings, missing years and one unit error. Then we clean it in a few lines.
import numpy as np, pandas as pd, plotly.express as px
from ms_charts import COLORS, PLOTLY_CONFIG
rng = np.random.default_rng(4)
# --- simulate a nested API response (fictional countries) ---
countries = [("Aurelia", 120), ("Borealis", 80), ("Caldera", 45),
("Deltora", 30), ("Equinox", 15)]
records = []
for c, start in countries:
level = start
for year in range(2005, 2026):
level *= 1 + rng.normal(0.035, 0.025)
# values arrive as strings, about 6% are missing
v = None if rng.random() < 0.06 else str(round(level * 1e9))
records.append({"country": {"id": c[:2].upper(), "value": c},
"date": str(year), "value": v})
# one record has a unit error (1000x too big)
if records[30]["value"] is None:
records[30]["value"] = "1e9"
records[30]["value"] = str(float(records[30]["value"]) * 1000)
# --- clean ---
df = pd.json_normalize(records) # flatten nested JSON
df = df.rename(columns={"country.value": "country"})
df["year"] = df["date"].astype(int)
df["gdp_bn"] = pd.to_numeric(df["value"]) / 1e9 # strings β numbers
med = df.groupby("country").gdp_bn.transform("median")
df.loc[df.gdp_bn > 20 * med, "gdp_bn"] = np.nan # drop the unit error
df["gdp_bn"] = df.groupby("country").gdp_bn.transform(
lambda s: s.interpolate(limit_direction="both")) # fill gaps
print(f"{df.value.isna().sum()} missing values filled, 1 unit error fixed")2 missing values filled, 1 unit error fixed
Show the code
fig = px.line(df, x="year", y="gdp_bn", color="country", markers=True,
color_discrete_sequence=[COLORS["indigo"], COLORS["teal"], COLORS["amber"], COLORS["rose"], COLORS["violet"]])
fig.update_layout(height=380, yaxis_title="GDP (billions, simulated)", xaxis_title=None, legend_title=None)
fig.show(config=PLOTLY_CONFIG)π‘οΈ Be a good data citizen
| Rule | Why | How |
|---|---|---|
| π Read the licence | Some data cannot be used commercially or needs attribution | Check the sourceβs terms page; cite it in your charts |
| β±οΈ Respect rate limits | Too many calls get you blocked | Sleep between calls, use bulk downloads when offered |
| πΎ Cache what you fetch | Re-downloading wastes time and quota | Save raw responses to Parquet or JSON with a date |
| π Hide your keys | Leaked keys get abused | Environment variables, .env files in .gitignore |
| π§Ύ Record provenance | You must be able to reproduce results | Log URL, parameters and download date |
| π Protect people | Even open data can identify individuals | Aggregate, drop identifiers, follow privacy rules |
A small helper that caches and retries covers most needs:
fetch.py
import time, json, pathlib, hashlib, requests
def fetch_json(url, params=None, cache="raw", retries=3):
h = hashlib.sha1(f"{url}{params}".encode()).hexdigest()[:16]
key = pathlib.Path(cache) / f"{h}.json"
if key.exists():
return json.loads(key.read_text()) # cached copy
for attempt in range(retries):
r = requests.get(url, params=params, timeout=30)
if r.status_code == 429: # rate limited
time.sleep(2 ** attempt); continue
r.raise_for_status()
key.parent.mkdir(exist_ok=True)
key.write_text(r.text)
return r.json()
raise RuntimeError("Gave up after retries")π§© Summary
- Start with Kaggle, UCI, OpenML and Hugging Face for ML practice; use FRED, World Bank, Eurostat, Census and OWID for economics and society; NOAA, NASA and OSM for climate and maps; BigQuery, AWS and Common Crawl for big data.
- Pick the extraction method from what the source offers: download β package β API β SQL or bucket.
- Flatten, convert, validate and cache what you fetch.
- Follow licences, rate limits and privacy rules.
- Put the data to work with a learning path π€οΈ.