Tony Wang6 min readHow to Scrape Numbeo in 2026 (API & Python)
Scrape Numbeo cost-of-living and quality-of-life data in 2026 — DIY, no-code, or a structured API — plus the real ToS and paid-API picture.
The fastest way to scrape Numbeo in 2026 is to call a structured API that returns normalized JSON — itemized cost-of-living prices and composite quality-of-life indices, per city or country — instead of parsing Numbeo's rendered pages yourself. Numbeo is the web's default source for city cost-of-living comparisons, and it does have an official API, but it's a paid commercial subscription rather than a quick free signup. This guide covers DIY, no-code, and a structured API, plus what Numbeo's terms actually allow.
Why scrape Numbeo?
Numbeo's crowdsourced price and index data anchors a specific slice of location research:
- Cost-of-living research — compare rent, groceries, restaurants, and utilities across cities for relocation planning or market analysis.
- Remote-work and digital-nomad tools — rank candidate cities by affordability, safety, and quality of life for a "where should I live" product.
- Real-estate affordability analysis — pair rent and property-price indices with local income data to score housing affordability by market.
- Salary and compensation research — adjust nominal salary offers by a city's cost-of-living index to compare real purchasing power across locations.
- Country- and region-level benchmarking — track how a country's cost-of-living or crime index compares to its neighbors, or how it moves period over period.
Is it legal to scrape Numbeo?
Option 1: DIY in Python (and why it breaks)
A DIY scraper requests a Numbeo city or index page and parses the rendered tables:
import requests
from bs4 import BeautifulSoup
resp = requests.get(
"https://www.numbeo.com/cost-of-living/in/Los-Angeles",
headers={"User-Agent": "Mozilla/5.0 (compatible; research-bot/1.0)"},
)
soup = BeautifulSoup(resp.text, "html.parser")
# Prices live in nested tables split across "Restaurants", "Markets",
# "Transportation", "Utilities", "Rent Per Month" sections — each needs
# its own row/column parsing logic
It demos and then breaks:
- The ToS explicitly restricts this. Numbeo's Terms of Use name automated scraping and crawling directly and require prior written permission — real risk, not a theoretical one.
- Nested, multi-section tables. Cost-of-living pages split prices across a dozen category tables (restaurants, markets, transportation, utilities, rent, and more); index pages split into their own titled sub-sections — each needs separate parsing logic that breaks on markup changes.
- No city discovery. Numbeo has no public city search or autocomplete — you have to already know (or scrape from a country/rankings page) the exact slug Numbeo expects.
- Index families multiply the surface. Quality of life, crime, health care, pollution, traffic, and property investment are each separate pages with different section layouts, so "get Numbeo data" is really six-plus different parsers.
Option 2: No-code tools
Marketplace scraper actors exist for one-off Numbeo pulls (cost-of-living tables exported to CSV), and they're a reasonable way to grab a snapshot for a spreadsheet. They don't hold up in a recurring pipeline — no scheduling, no normalized schema across cities, and the same Terms of Use exposure as DIY since Numbeo requires permission for automated collection regardless of the tool doing it.
Option 3: A structured Numbeo API
For a repeatable, permission-scoped workflow, a Numbeo scraping API returns normalized JSON with no page parsing to maintain. Pull a city's cost of living:
curl "https://api.crawlora.net/api/v1/numbeo/cost-of-living/city/Los-Angeles" \
-H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"city": "Los Angeles, CA",
"city_slug": "Los-Angeles",
"country": "United States",
"categories": [
{
"category": "Restaurants",
"items": [
{ "name": "Meal at an Inexpensive Restaurant", "currency_symbol": "$", "price": 25, "range_low": 16, "range_high": 45 }
]
},
{
"category": "Rent Per Month",
"items": [
{ "name": "1 Bedroom Apartment in City Centre", "currency_symbol": "$", "price": 2563.18, "range_low": 2000, "range_high": 3400 }
]
}
],
"contributors_12mo": 178,
"last_update": "13 July 2026",
"source_url": "https://www.numbeo.com/cost-of-living/in/Los-Angeles"
}
}
Numbeo has no public city search endpoint, so discover a valid city_slug from the country endpoint first, then pull an index — quality of life, crime, health care, pollution, traffic, or property investment — for the same city:
import requests
h = {"x-api-key": "YOUR_API_KEY"}
base = "https://api.crawlora.net/api/v1/numbeo"
# Discover city slugs for a country
country = requests.get(f"{base}/cost-of-living/country", headers=h, params={"country": "United States"}).json()["data"]
slug = country["cities"][0]["city_slug"]
# Cost-of-living detail for that city
col = requests.get(f"{base}/cost-of-living/city/{slug}", headers=h).json()["data"]
# Crime index for that city
crime = requests.get(f"{base}/indices/city/{slug}", headers=h, params={"index": "crime"}).json()["data"]
The indices endpoints return a shared envelope regardless of index — headline values plus (for most families) titled sub-sections of individual metrics:
{
"code": 200,
"msg": "OK",
"data": {
"index": "crime",
"city": "Los Angeles, CA",
"city_slug": "Los-Angeles",
"country": "United States",
"headline_indices": [
{ "name": "Crime Index", "value": 53.83 },
{ "name": "Safety Index", "value": 46.17 }
],
"sections": [
{
"title": "Crime rates in Los Angeles, CA, United States",
"rows": [{ "name": "Level of crime", "value": 61.08, "qualifier": "High" }]
}
],
"contributors_note": "Contributors: 486",
"last_update": "13 June 2026",
"source_url": "https://www.numbeo.com/crime/in/Los-Angeles"
}
}
Ranking endpoints (cost-of-living/rankings, cost-of-living/rankings-by-country, indices/rankings, indices/rankings-by-country) work the same way and accept scope/period on the current-scoped endpoints for historical snapshots where Numbeo publishes them. Store one row per city or country and re-run on a schedule.
What you can collect
Per-city and per-country cost-of-living data: itemized prices by category (restaurants, markets, transportation, utilities, rent, and more) with price, range_low, range_high, and currency symbol, plus the six headline cost indices (cost_of_living_index, rent_index, cost_of_living_plus_rent_index, groceries_index, restaurant_price_index, local_purchasing_power_index). Per-city and per-country index data for six families — quality of life, crime, health care, pollution, traffic, and property investment — as headline values plus titled sub-index breakdowns. Ranked city and country lists for both families, with contributors_12mo/contributors_note and last_update metadata on every response. Public data only.
Limitations and common challenges
- Crowdsourced, not audited. Numbeo's prices come from site visitors submitting what they pay —
contributors_12moandcontributors_notetell you the sample size behind a number, and a city with a few hundred contributors (Los Angeles, Zurich) is far more reliable than one with a handful. Treat low-contributor cities as directional, not precise. - No city search endpoint. There's no autocomplete — resolve a
city_slugfrom a country or rankings response before requesting city detail. - Six separate index families. Quality of life, crime, health care, pollution, traffic, and property investment each return a different response shape (some have
sections, property-investment hasprice_categoriesinstead) — plan your schema per family, not one generic shape. - ToS-gated for scale. Numbeo's own terms require written permission for automated collection and a paid plan for commercial use — scope any project to what's genuinely public reference use, and go through Numbeo's own API or license for heavy commercial redistribution.
- Public data only. This collects what Numbeo already displays publicly — never a way to build a competing cost-of-living database at Numbeo's scale.
Where this gets used
- Relocation and remote-work tools — rank cities by affordability and quality of life for a location-decision product.
- Compensation research — adjust salary figures by a city's cost-of-living index to compare offers across markets.
- Real-estate affordability models — pair rent and property indices with income data to score housing markets.
- Market and country research — benchmark a country's cost, safety, and health-care indices against peers.
Sources
Start collecting
Try it first, free: run any public URL through the Free Web Scraper, or check whether a site blocks bots with the Anti-Bot Checker — no signup.
Test the cost-of-living and indices endpoints in the Playground, check the schema in the API docs, and review pricing. Cost of living tells you what things cost; Yahoo Finance tells you what people earn from markets and salaries in that same economy — pair the two for real purchasing-power research. If housing affordability is the angle, how to scrape real estate listings pairs directly with Numbeo's rent and property indices for a full cost-of-living-plus-housing picture.
Part of our how-to-scrape guide series — every platform we cover, in one index.
Frequently asked questions
Does Numbeo have an official API?
Yes — Numbeo sells a paid Data API with monthly plans starting at $260/month for 200,000 queries, billed through FastSpring. It's not a free self-serve signup, which is why a structured scraping API is a lower-friction option for lighter or research use.
Is it legal to scrape Numbeo?
Numbeo's Terms of Use prohibit automated scraping or crawling without prior written permission, though personal, academic, and journalistic use of publicly displayed data is allowed with attribution. Commercial use requires one of Numbeo's paid plans or a data license.
How reliable is Numbeo's cost-of-living data?
It's crowdsourced from site visitors rather than audited, so reliability tracks contributor count — high-contributor cities like Los Angeles or Zurich are far more dependable than small towns with only a handful of submissions.
How do I find a city's Numbeo slug?
There's no public city search endpoint. Call the cost-of-living/country or indices rankings endpoints for a country and read city_slug off the returned cities array.
What index families does Numbeo track?
Six: quality of life, crime, health care, pollution, traffic, and property investment. Each returns headline index values plus, for most families, titled sub-index sections or itemized price categories.
Can I get historical Numbeo rankings, not just current?
The ranking endpoints accept scope and period parameters for historical snapshots where Numbeo itself publishes that history.
What's the difference between cost-of-living and indices data?
Cost-of-living endpoints return actual itemized prices (rent, groceries, restaurant meals). Indices endpoints return composite normalized scores (0-100+ scale) for quality of life, safety, and similar dimensions.