Travel index · 2026

Can you take a call from that room?

Hotels advertise free high-speed WiFi and publish no number. Pingpillow joins OpenStreetMap's lodging to Ookla's open speed-test tiles and answers the question you actually have: what the connection at this address measures, whether the upload holds a video call, and — where nobody has ever run a test — how far the nearest real measurement is and in which direction.

Pingpillow on screen
6.4M
measured speed tiles behind every lookup
2,005,444
places scored, from city hotels to shepherd camps
8
quarters of history, so a location getting worse is visible
0
outbound calls on the page a crawler sees
Built with
PythonDuckDBParquetSQLiteStarletteLeafletsystemdCaddy

Ranking neighbourhoods and calling it a hotel ranking

The first city page put six hotels at the top with identical speeds to one decimal place. Scoring in bulk averaged a 3×3 block of tiles around each hotel, so every property on the same street got one number — a ranking of neighbourhoods wearing a ranking of hotels. It now takes each hotel's own 600 m tile wherever that tile has the tests to support it and widens only for the ones that don't: 1,049,975 of 2,005,444 scored places resolve at their own tile, and the ties that remain are hotels genuinely sharing one block.

The conclusion that was really my own typo

Probing the villages this was built for — Jibhi, Shoja — returned nothing within 8.6 km, for fixed and mobile both. The obvious reading was that the open data stops where the tourists do, and that the whole premise failed exactly where it mattered. The coordinates were mine, typed from memory, 35 km up the wrong valley. Geocoded properly, Shoja measures 104 down and 88 up on 24 tests. The dataset was never the problem; the input was, and it was confident either way.

A mirror that answered 200 and meant nothing

Overpass mirrors fall over under load, so failures rotate to the next one. One of them, overpass.osm.ch, holds only Switzerland — it answered an Indian bounding box with HTTP 200 and an empty result set. Seeding reported every Himachal village as having no hotels, which is indistinguishable from the truth for a village that has none. An empty answer is now treated as a failed mirror and retried elsewhere, believed only on the last attempt.

Nothing the crawler touches leaves the box

The point of the site is pages Google can index, which means a crawler walking thousands of hotels. Serving those from the upstream parquet would have rate-limited the project off its own data sources with its own traffic. So the read path touches nothing but SQLite — every number precomputed — and a separate worker owns every outbound call. Pages render in single-digit milliseconds and the quarterly refresh is a cron job nobody has to remember.