Methodology
Every number on a city page comes from a specific data source and a specific formula. This page documents both — what we measure, where the data comes from, and what each figure does and doesn't capture about real visitor experience.
Want to play with the formula? → Interactive scoring explorer — sliders for temp, humidity, wind, sun, rain. Watch the score and every sub-index recompute live as you drag.
Climate score (HCI)
The 1–10 score that drives the colour of every cell. Built on the Holiday Climate Index (Scott, Rutty & Amelung, 2016) — a published tourism-climate standard run operationally by the EU's Copernicus Climate Change Service. Four sub-indices, each 0–10, weighted and summed to 0–100; shown here scaled to 1–10.
Our figures use HCI's structure and weights with two additions: the thermal component is computed on outdoor apparent temperature (Steadman / BoM form, wind-aware) rather than raw temperature, and a graduated override gate caps the composite when heat or cold crosses a deal-breaker. Treat them as HCI-family, not a verbatim reproduction of the published tables.
Four sub-indices
- Thermal
-
Outdoor apparent temperature ("feels-like"): daily-max temperature
with humidity and wind folded in via the Steadman / BoM formula:
AT = T + 0.33·e − 0.70·v − 4, where e is vapour pressure derived from relative humidity. Multiplied by an inverted-U humidity factor — comfort is best around ~50% RH and degrades toward both muggy and bone-dry. - Sky
- Cloud cover, proxied by sunshine hours (corrected for Open-Meteo's permissive threshold). Capped by rain-hours so a perpetually-drizzly month can't claim a clear-sky score whatever the sunshine total says.
- Rain
- Blends rain-days (frequency) with rain-hours (duration). Light rain tolerated; heavy continuous rain penalised steeply. Our rain-hours dimension is what HCI doesn't have — lets us distinguish prolonged drizzle from brief intense bursts when day-counts are otherwise identical.
- Wind
- A light breeze is ideal (~10 km/h mean wind); dead calm is mildly penalised; strong wind is heavily penalised. Input is approximate mean wind derived from daily-max wind speed.
Trip-type profiles
The four sub-indices are weighted differently by trip type, and the thermal "comfort plateau" itself sits in a different temperature range:
| Profile | Thermal | Sky | Rain | Wind | Comfort plateau |
|---|---|---|---|---|---|
| Urban | 4 | 2 | 3 | 1 | 20 → 27°C apparent |
| Beach | 2 | 4 | 3 | 1 | 20 → 27°C (beachgoers can swim to cool off) |
| Winter | 3 | 4 | 2 | 1 | −10 → +4°C (cold is the point) |
Use Winter for ski, aurora, and Christmas-market tourism — heat in this mode is the deal-breaker (a 10°C thaw caps the score the way a 35°C heatwave does on the urban curve).
Override gate — deal-breaker heat & cold
Adapted from the Camping Climate Index (Ma, Craig & Feng, 2020). When apparent temperature crosses a deal-breaker threshold (plateau edge plus a small offset), the whole composite is capped — clear skies and dry weather can't prop up a month that's genuinely unvisitable. The breakdown panel shows the un-capped factor total alongside the capped result so the gate's effect is transparent.
Slope is 6%/°C above the heat threshold (caps to 0.3 floor at large excesses); 4%/°C below the cold threshold (caps to 0.4 floor). The visual "gated" treatment (grey factor bars, corner dot) only shows when the cap actually bites — a 5% reduction doesn't shout "extreme" because the underlying HCI math is honest either way.
Day & Night temperature strips
Two thin strips below the main score heatmap, shared thermometer palette (blue → green → red across −10..36°C). Day is the monthly mean of daily-max temperatures; Night the monthly mean of daily-min. Read the pair to spot diurnal patterns at a glance:
- Sedona summer: red day strip over green night strip → big cool-off, desert relief possible.
- Singapore: orange day over orange night → no relief, perpetual heat.
- Barcelona August: warm day, mild night climatologically — but the tropical-nights count tells the stickier truth.
These are monthly means of daily extremes, not the hottest single day. Tail-day reality is captured by the heatwave-days strip.
Heatwave days (TX35)
Monthly strip below the day/night strips, fires when the city has any heatwave-day signal. Shows the average number of days per year with daily-max temperature ≥35°C, computed over the recent window (2020–2024). Hover a cell to see the worst-single-year count too.
TX35 is an ETCCDI (Expert Team on Climate Change Detection and Indices) extreme-climate indicator used in IPCC reports. The threshold is universal — same 35°C floor everywhere — which means it works well for continental / Mediterranean / desert climates where dry-bulb peak is what matters, and undershoots for humid coastal cities where 32°C with 75% RH is the actual oppression (Barcelona's TX35 reads "essentially 0" but residents still suffer; see tropical nights).
Computed from the same daily ERA5 series we use for the climate score, so no additional data source — the heatwave-days chart is free precision on top of the existing scoring pipeline.
Tropical nights (TR20)
Monthly strip showing the average number of nights per year where daily-min temperature ≥20°C. Same recent window (2020–2024). Hover for the worst-single-year count.
TR20 is the other half of the ETCCDI extreme-temperature pair, and for humid coastal cities it's often the more important metric than TX35. Sleep is the constraint — a Barcelona August with daytime peaks at "only" 29°C is still oppressive when 26 of 31 nights stay above 20°C (verified against r/AskBarcelona resident testimony). The 20°C threshold is calibrated for temperate Europe; in the tropics every night clears it, so the metric saturates for Singapore / Bali / Bangkok (~31/31 nights, every month).
Chip in the per-month panel fires when avg ≥3 nights/yr AND peak ≥5, with purple framing to distinguish from the orange heatwave-day chip.
UV index
Monthly strip below the heatwave / tropical-nights strips, colour-coded by WHO/WMO band:
| UV index | Band | What to do |
|---|---|---|
| 0–2 | Low | Minimal protection needed |
| 3–5 | Moderate | Sunglasses, SPF on exposed skin |
| 6–7 | High | Limit midday sun; SPF 30+ |
| 8–10 | Very high | Limit exposure 11:00–17:00; SPF 50, hat |
| 11+ | Extreme | Avoid midday exposure entirely |
Units. UV index is a unitless calibrated scale defined by the World Health Organization, World Meteorological Organization, and ICNIRP. One unit ≈ 25 mW/m² of erythemally- weighted UV radiation (the wavelengths that cause sunburn). The bands above, not the raw number, are what matters for behaviour.
What we show — typical day. The main UV strip is the monthly mean of daily-peak UV (typically near solar noon), weather-modulated by cloud cover. Layman: on a typical day around midday, UV is about this. A chip fires in the per-month panel when the monthly average is in the very-high band (≥8). Strip cells show the integer value with the WHO band colour underneath.
What we show — bad days (warning sub-strip). Below the main strip, a sparse second row fires only when the mean understates the band. Each fired cell is the 90th-percentile of daily-peak UV for that month — the floor of the worst ~10% of days. Layman: on the sunniest 1 in 10 days, UV reaches this — and even higher.
When the warning fires. Two triggers, both targeting "the mean is misleading":
- Band-jump. The p90 lands in a higher WHO band than the mean. Example: London June — mean UV 5 (moderate, just SPF and sunglasses) but p90 7 (high, midday limit). A reader who only sees the mean would under-prepare.
- Same-band escalation. p90 stays in the same band but is ≥ 1.5 UV units above the mean. Example: Singapore March — both round into very-high, but the worst 10% of days routinely hit the band ceiling and beyond. Worth flagging even though the band label is unchanged.
Why p90 over mean / max / Tukey. The mean answers "what's typical." The single-day max is one freak observation — statistically meaningless for planning. Tukey's 1.5·IQR rule is for anomaly detection, not characterising bad days; for tight distributions it can land above the maximum and flag nothing. p90 is robust ("top 10%" — moves ~9 days per month to shift) and directly actionable: it's the level you'd encounter if you spent ten typical days in the city.
Sparseness is the design. When no month fires, the warning row doesn't render at all. When a city fires only its shoulder months — Dubai shows warnings on Mar/May/Oct/Nov — the remaining slots stay invisible, so the row reads as "these are the months where the mean misleads." Steady high-UV cities still fire on cells where the worst-10% reach a higher band; variable mid-latitude cities concentrate warnings in summer (London May–Aug).
Source. CAMS (Copernicus Atmosphere Monitoring
Service) via Open-Meteo's Air Quality API. Coverage starts ~Sept
2022 — note the per-city uv_period caption for the
exact span used. UV is not in the ERA5 archive we use for
the rest of the climate data, so this metric has a shorter
historical window (3–4 samples per month, vs 5 years for temp /
precip / humidity).
What it doesn't capture. Altitude effects (UV increases ~10% per 1000 m), snow/water reflection (adds 25–80% to skin dose), and individual-hour extremes. The warning sub-strip captures day-to-day variance — between-day spread within a month — but not within-day swings: the early-morning vs noon difference is not represented.
Air quality (PM2.5)
Fine-particulate concentration in micrograms per cubic metre (µg/m³). The dominant outdoor-air health metric — PM2.5 is small enough to lodge deep in the lungs and cross into the bloodstream. Travel-relevant cases: Krakow winter coal-heating, Po Valley inversion smog in Milan, agricultural burning in Bangkok and northern Thailand, regional haze in Singapore, year-round pollution in Beijing.
What we show. A two-row strip pair placed immediately below the main month-nav score heatmap (the "JAN 7, FEB 8…" colored boxes). Both rows always render when PM2.5 data exists for a city. The top row is the monthly mean of daily means (typical-day exposure). The bottom row is the 90th-percentile of daily means — the worst-10%-of-days floor. Cells on either row are coloured by WHO band: greens for clean cities, oranges and reds where the air degrades.
Why always both, instead of hiding p90 when it doesn't cross a threshold? Because hiding it loses the contrast a reader needs to judge "how much worse can the bad days get than the typical day". Faro's typical day is PM2.5 ~8 µg/m³ but the worst 10% of days reach ~13 — both clean, but visibly different, and that's worth surfacing. The "warning" framing moves from "the row appears" to "the row contains orange or red cells" — same signal, no surprise gap.
| PM2.5 µg/m³ | Band | What to do |
|---|---|---|
| 0–5 | Good | WHO guideline met; minimal concern |
| 5–10 | Fair | Well within interim target 4 |
| 10–15 | Moderate | Interim target 3 territory |
| 15–25 | Unhealthy for sensitive | Asthma, kids, elderly: limit prolonged outdoor activity |
| 25–35 | Unhealthy | General population: avoid heavy outdoor exertion |
| 35+ | Hazardous | Avoid prolonged outdoor exposure |
Captions on the page. Match the UV pair so the two surfaces read the same way:
- "PM2.5 air quality · on a typical day" — mean row, always rendered when we have data.
- "On the worst 1 in 10 days, PM2.5 reaches this — and even higher" — p90 row, fires only on warning months.
Source. CAMS (Copernicus Atmosphere Monitoring
Service) via Open-Meteo's Air Quality API. Hourly modelled PM2.5
aggregated to daily means, then monthly mean and p90 per city.
Same coverage window as UV (~Sept 2022+); see aq_period
on each city for the exact span used.
Honest caveat. Air pollution varies year-to-year more than climate — Delhi winter swings with policy, Bangkok burning seasons shift with rainfall, wildfire smoke is increasingly unpredictable. The numbers reflect typical recent months and could be materially different in any specific year. Check current air-quality readings (e.g. iqair.com, aqicn.org) close to your trip date for live conditions.
What it doesn't capture. O3 (ozone), NO2, PM10, and SO2. PM2.5 is the dominant outdoor health metric but not the only one — in some cities ozone is the primary concern instead (LA basin, Mexico City summer). May be added as separate surfaces in future.
Sea temperature
Shown for beach destinations as a separate strip and a per-period number — kept outside the climate score because the appeal curve isn't monotonic (warm is good up to a point; "bathtub" warm collapses the appeal because you can't cool down by swimming).
- <18°C — cold: wetsuit / hardy swimmers only.
- 18–21°C — chilly: doable, bracing.
- 22–26°C — ideal: refreshing on a hot day, swimmable.
- 27–28°C — warm but tolerable.
- 29–30°C — bathtub: appeal collapses.
- ≥31°C — too warm: actively unpleasant.
Sources: recent window from Open-Meteo's marine archive (hourly SST since Nov 2022); 1991–2020 normal from NOAA OISST v2.1 (daily 0.25° optimum-interpolation SST since 1981). Both dekad-averaged to the same 36-bucket grid as the air-temperature panels.
Interest seasonality
The violet strip above the main climate strip. What it measures: Google search interest for "City name travel" over 2021–2025, monthly resolution, per-city renormalised so the quietest month = 0 and the busiest = 100. The metric itself is reliable — it's a direct, honest count of search activity.
What it does not measure: actual crowds. Search activity is a mix of researchers (planning 6-12 months ahead), imminent-trip planners (1-3 months out), in-trip tourists searching mid-stay, and locals searching for local events. We can't decompose those cohorts. So read the seasonal shape as "this destination is on people's minds" — useful as a planning proxy, not as an arrivals chart.
Not folded into the climate score: high interest usually tracks the best weather, so penalising it would invert the ranking. The information is here for readers deliberately seeking quieter months or wanting to time their search against the booking-pulse.
See what we don't model for the future plan on actual arrivals data (Amadeus) — a different signal we'd render as a separate strip alongside this one, not as a replacement.
What we don't model
Every site like this has gaps. Ours, candidly:
- Real crowd / arrivals data. The Interest strip shows what we do measure (search activity) — accurate but not the same as actual arrivals. Amadeus's busiest-period ARRIVING endpoint would give a real "who's there when" signal; on the roadmap as a second strip alongside Interest, not a replacement.
- Pollution / AQI. Air quality matters for experience (Beijing winter, Bangkok dry season, Delhi anytime). On our roadmap.
- Pollen / hay-fever load. A real factor for spring-peak destinations. Not currently modelled.
- Tides, festivals, blooms, aurora. Destinations where the answer to "when to visit" isn't climate — Mont Saint-Michel (tides), Kyoto cherry blossom timing, Iceland aurora KP-index forecasts. We deliberately exclude these for now; see the Landmarks section on the homepage for our climate-only landmark roster.
- Real-time / forecast data. Everything here is climatology (typical for the month over recent years). For "what's actually happening this week" you'd want a live forecast — out of scope.
- Year-to-year variability. Climate is a multi-year average; an actual August can run hotter or wetter than typical. The heatwave-day "peak" hover text gives some sense of the worst single-year value in the window.
Sources & references
Primary data sources:
- Open-Meteo ERA5 archive — daily temperature, precipitation, sunshine, wind (1991–present). Used for all climate scoring + heatwave / tropical-night day counts.
- Open-Meteo hourly archive — relative humidity (1991–present), filtered to daytime 10:00–18:00.
- Open-Meteo Air Quality API (CAMS) — UV index (~Sept 2022–present).
- Open-Meteo marine archive — sea surface temperature (hourly since Nov 2022).
- NOAA OISST v2.1 — 1991–2020 sea-temperature normal climatology.
- Google Trends — monthly search interest per city (2021–2025).
Scoring literature:
- Scott, D., Rutty, M., Amelung, B. & Tang, M. (2016). "An Inter-Comparison of the Holiday Climate Index (HCI) and the Tourism Climate Index (TCI) in Europe." Atmosphere.
- Rutty, M., Scott, D., Matthews, L., Burrowes, R., Trotman, A., Mahon, R. & Charles, A. (2020). "An Inter-Comparison of the Holiday Climate Index (HCI:Beach) and the Tourism Climate Index (TCI) to Explain Canadian Tourism Arrivals to the Caribbean." Atmosphere.
- Steadman, R.G. (1994). "Norms of apparent temperature in Australia." Australian Meteorological Magazine, 43(1).
- Ma, S., Craig, C. A. & Feng, S. (2020). "Climate suitability for tourism in China: Application of the Climate Index for Tourism (CIT)." Tourism Geographies.
- Frich, P., Alexander, L. V., Della-Marta, P., et al. (2002). "Observed coherent changes in climatic extremes during the second half of the 20th century." Climate Research (ETCCDI TX35 / TR20 indicators).
- WHO / WMO / ICNIRP. Global Solar UV Index: A Practical Guide. WHO publication, 2002.
Want to play with the math yourself? The interactive explorer lets you drag sliders for temp, humidity, wind, sun, and rain and watch every sub-index recompute live — same function as the city pages.