Climate normals
Primary
SourceWeather-station climate normals for 1991-2020 where a station stands for the city (WMO Climate Normals 1991-2020 via NOAA NCEI; IDEAM, Colombia's met service; Meteostat and its data providers, CC BY 4.0; and, for stations missing from the WMO set, the normals PAGASA, Nepal's DHM, the India Meteorological Department and Meteo-France publish themselves), Open-Meteo ERA5 reanalysis for 2019-2023 everywhere else
Retrieved5 October 2026
HowEach city takes the nearest station that publishes 1991-2020 normals (mean daily high, mean daily low, monthly precipitation) when it is within 25 km of the city coordinate and within 250 m of the city's elevation; airports and WMO-indexed stations are favoured by 3 km and a national met service file beats Meteostat for the same station. Stations absent from the WMO set are transcribed from the met service's own file (data/climate-national-normals.json, with the file URL per station); four of them have no published 1991-2020 normal, so their own period is used and named on the page: Iloilo 1991-2009 and Tagbilaran (Bohol) 1991-2013 from PAGASA, Kochi's naval air station and Madikeri (Coorg) 1981-2010 from IMD. Values are rounded, never adjusted for elevation or interpolated. Stations are dropped when their file coordinate disagrees with the station register or with the ground elevation, when a country's WMO submission reports extremes rather than daily means (Mongolia, Turkmenistan, Armenia, Oman, Niger), when any month fails a sanity check, and in three reviewed cases (a Meteostat Iloilo record 3-5C too cool against PAGASA's own sheet, Leh, one Nanaimo record). The remaining cities keep the ERA5 grid values from scripts/build_city_climate.cjs. Built by scripts/build_climate_stations.cjs; the source, station, distance and elevation difference for every city are in data/city-climate-source.json.
999 of 999 cities: 645 from a weather station (WMO 413, Meteostat 215, IDEAM 9, other national met services 8), 354 from the ERA5 grid
What this does not coverPeriods are mixed: station cities show the 1991-2020 normal (four show their station's own published period, see method), ERA5 cities the 2019-2023 average, a later and warmer window whose rain rests on five years only. Read the rest
ERA5 is a grid of roughly 25 km cells: against the 645 stations its annual rain was 1.12 times the measured figure at the median and off by a factor of 1.5 or more for 84 cities, mostly in mountains and on wet tropical coasts; its highs ran 0.7C cooler at the median and were more than 2C off for 81. The 354 ERA5 cities carry that margin; 12 of them are flagged in data/city-climate-source.json because the stations around them show the grid too wet or too dry. A station up to 25 km away can sit in a different microclimate (an inland airport for a coastal town has colder nights), and up to 250 m of height difference is about 1.6C.
Climate source per city
Primary
SourceThe station registers and normals files named in the climate entry
Retrieved5 October 2026
HowFor every city: whether its climate normals come from a weather station or the ERA5 grid, and for a station its name, identifier (WMO index where it has one), provider, period, distance from the city coordinate and elevation difference, and the file URL for a station transcribed from a national met service. The ERA5 values a station replaced are kept beside it. Written by scripts/build_climate_stations.cjs and quoted under the weather chart of every city guide.
999 of 999 cities: 645 station, 354 ERA5, of which 12 flagged as doubtful against nearby stations
What this does not coverDistances are measured from the coordinate the site stores for the city, which is a point in the centre, not the edge of the built-up area.
Time zones
Primary
SourceIANA Time Zone Database
Retrieved6 August 2026
HowZone resolved from each city's coordinates with tz-lookup, then evaluated at runtime by the Intl API so DST is always current.
city-airports
Primary
SourceOurAirports
Retrieved4 September 2026
HowEvery city is mapped to the airport a traveller would actually fly into, from the airports.csv OurAirports publishes into the public domain. Read the rest
Only airports with an IATA code and scheduled service are eligible: an airfield you cannot buy a ticket to is not an answer. Distance is straight-line from the city coordinate and is discounted by 60km for a large hub and 25km for a medium one, so a hub slightly further out beats a nearer regional strip, capped at 250km. Straight-line distance knows nothing about water or hard borders, so eight cities are set by hand where the nearest airport is unreachable in practice, each with its reason recorded in scripts/build_city_airports.cjs. Cities with nothing in range are recorded as unserved rather than pointed at a guess.
890 of 891 cities, 1 unserved
City photographs
Primary
SourceWikimedia Commons file pages
Retrieved6 August 2026
HowPhotographer, licence and file page recorded per image in images/cities/attribution.json and shown as a visible credit on the page. Only PD, CC0, CC BY and CC BY-SA accepted.
1002 images
Cost of living components
Primary
SourceNumbeo cost-of-living index
Retrieved1 October 2026
HowComponent prices scraped per city in local currency exactly as Numbeo reports them, converted to USD at apply time. Read the rest
Numbeo is itself crowd-sourced, so it is primary only for the Numbeo index, not for ground truth. Retrieval dates: 2026-08-05 (most cities); 2026-09-29 and 2026-10-01 (86 cities fetched directly from numbeo.com).
What this does not coverNumbeo sample sizes are small in less-visited cities and its 'last updated' date varies widely per city.
Elevation
Primary
SourceOpen-Meteo Elevation API (Copernicus DEM GLO-90)
Retrieved9 August 2026
HowElevation sampled at each city's stored coordinate. Not published; used by scripts/check_data_sanity.cjs to catch island and region centroids that land on high ground.
Monthly budget range
Primary
SourceNumbeo cost-of-living components, converted to USD at exchangerate-api.com
Retrieved5 August 2026
HowThe low end is a one-bedroom outside the centre plus the one-person no-rent basket; the high end is the same basket with a one-bedroom in the centre. Read the rest
Rent varies, the basket is held constant, because groceries and transport do not change with the neighbourhood and Numbeo does not split them by one anyway. Built by scripts/build_cost_range.cjs, rendered by apply_cost_range.cjs, checked by check_cost_range.cjs.
412 of 999 cities. Three more (Leon, Noumea, Plymouth) are excluded because Numbeo reports rent outside the centre as higher than or equal to rent in it, which would render backwards, and Punta Cana has no rent outside the centre on Numbeo.
What this does not coverThe 583 estimated cities show a single estimate and no range, deliberately. Read the rest
They hold no cost components, so the only way to derive a second end was to read a rent range out of their own page prose. Tested against the 330 cities where the true figures are known, that method missed by 23% at the median and by more than 50% on 72 of 488 endpoints, so it was not used: a range nobody measured would look exactly like one we did. The range is also only as good as Numbeo's idea of where the city ends, and it covers rent and a basket, not flights, visas, insurance or health care.
Service providers by language
Primary
SourceOfficial lists first: embassy and consulate lists of providers by language, statutory registers (Japan's Ministry of Health, Labour and Welfare medical register, the Styrian doctors' chamber) and city and national government open data (Seoul, Daegu, Korea Health Industry Development Institute); then the provider's own website
Corroborated againstbangkok.diplo.de/th-de/service/aerzteliste-1506722, www.iryou.teikyouseido.mhlw.go.jp, www.aekstmk.or.at/cms/cms.php?pageName=46, data.seoul.go.kr/dataList/OA-12967/F/1/datasetView.do, Each provider's own page on its source, recorded per row as sourceUrl in data/service-languages.json
Retrieved24 September 2026
HowEvery row records the exact URL the language claim was read on and an evidence tier: official (a government or embassy list defined by working language), self-declared (the provider's own site), directory (a third-party aggregator only), or visited (we confirmed in person; unused so far). Read the rest
scripts/build_services.cjs refuses to build if any row lacks a sourceUrl, a known evidence tier, a known language or a real city slug. The tiers are printed on every card. scripts/verify_service_links.cjs re-fetches every url and sourceUrl and reports status, redirect target and page title, so a link that rots or starts pointing somewhere else is caught rather than assumed; the 2026-08-12 runs removed one row whose cited article did not contain the claim, dropped two invented domains, corrected a link that redirected to the wrong branch, and later dropped five more rows whose sources turned out to be a dead domain, a 404, an unreachable directory, or a site that never actually states a spoken language. The checker retries three times before calling a link dead, because a single transient failure once reported six healthy URLs as dead. One live site (vetinlisbon.pt) refuses Node's fetch entirely and was confirmed by hand.
70373 providers across 566 of 999 cities, 15 service types and 56 languages. 70064 official, 174 self-declared, 115 directory. Prague 7315, Bucharest 5672, Hamburg 4714, Melbourne 4396, Tokyo 3634, Buenos Aires 3375
What this does not coverTHE EVIDENCE MIX SHIFTED ON 2026-08-12. Read the rest
An owner decision to grow volume via aggregator directories took the directory tier from 39 rows to 105, roughly half the set, so the average row is now weaker than when the dataset was 62 rows. Many directory rows rest on a ROSTER-LEVEL claim ("the clinics we list speak English") rather than a statement about the named business; each such row says so in its note. PRIMARY FOR THE CLAIM, NOT FOR FLUENCY. We source that a provider is stated to work in a language; we have not verified that it does, and no row carries the 'visited' tier. A hospital offering interpretation is counted under the languages it interprets, which is not the same as a doctor speaking them: Chiang Mai Ram and Thonglor Pet are interpreter desks, not multilingual clinicians. The 17 directory-tier rows rest on guides and aggregators that may sell placement, making them the weakest entries. The US Consulate Chiang Mai health-facilities and legal-provider PDFs and the US Embassy Georgia mental-health resource PDF are all image-only or protected and could not be read; retrieving those would upgrade several rows and is the obvious next improvement. A Russian-language directory of Russian-speaking doctors in Georgia (needdoc.ru) is an unexploited language-defined source of the same kind. Coverage is a pilot, not a map of any city's real provision, so absence from this list means nothing. REGISTERS (2026-09-24). Japan's register is the facility's own statutory report; only Tokyo's form asks whether a language is accepted without prior consultation, so Tokyo rows require that yes while the other seven cities publish the listed language unless the facility's own note hedges it (translation device, interpreter, call first, a few words). Facilities listing more than six languages and employer clinics are refused. Korean city lists are compilations by a city or district, not statutory reports, and Seoul's pharmacy list is dated 1 January 2023. The Korea Health Industry Development Institute lists language services a hospital offers, which may be an interpreter rather than the doctor.
internet-speeds
Primary
SourceOokla Speedtest Global Index
Retrieved1 October 2026
HowMedian fixed-broadband and mobile download speeds read from each country page of the Global Index (the latest edition per metric, August 2026 for most), plus Ookla's own city medians where it publishes them. Read the rest
Stored in Mbps exactly as published and quoted rounded on the WiFi score tile of each city page that gives a speed. Metrics older than March 2026 or out of line with their own history are left out rather than filled. Extended on 2026-10-01 to every country in cities-data.js that has a Global Index page, under the same rules. Retrieval dates: 2026-09-29 (105 countries); 2026-10-01 (38 countries added).
143 countries: every country in cities-data.js for which Ookla publishes a current figure. 144 Ookla city medians, keyed by city id (Hong Kong from its own SAR market figures). 67 countries and territories in cities-data.js have no entry: 59 have no Global Index page at all, 7 have only a fixed series older than March 2026, and the Maldives has no usable figure (listed in _meta).
What this does not coverNational medians, not city measurements, except where a named Ookla city median is held. Read the rest
Speedtest results are user-initiated tests, so they lean toward people who test their connection. Ookla publishes no current mobile median for 39 of the 143 countries and no current fixed median for 2 (Eswatini, Eritrea). Small or new series (Barbados, Eritrea, Turkmenistan: two editions each) pass the same rules but carry more sampling noise.