Docs
Built in Bangkok · location data for Thailand

Thailand breaks map APIs. It shows up in your P&L.

Failed deliveries, abandoned checkouts, and a data team reconciling four spellings of the same district. One clean, multilingual view of Thai geography instead.

Scroll to zoom in
The business case
Your numbers, not ours

What bad geography costs you
every month.

An address that doesn't resolve doesn't fail quietly. It becomes a call to the customer, a second delivery attempt, a driver idling in the wrong soi, or an order that never gets placed.

Most companies carry this as a cost line they've never named.

Estimateaddress failure exposure
failed addresses / month2,000
cost / month฿240,000
cost / year฿2,880,000

Defaults are placeholders, not benchmarks. This ignores the customers who never came back, which is usually the larger number.

Last-mile logisticsE-commerceProperty portalsRide-hailingRetail expansionField services
Data quality
Engineering weeks you stop spending

Your team stops reconciling
place names by hand.

Pull Bangkok from three sources and you get three cities: Bangkok, Krung Thep, Krung Thep Maha Nakhon, sometimes Bangkok Metropolis — with the Thai in a different field and the Chinese missing.

Every join written on those strings is a bug waiting for a release. Here, every alias points at one permanent id.

Try itsend any name you have
Pick a place, then a messy spelling of it
you sentBangkok
resolves toth:10
typeprovince
official (th)กรุงเทพมหานคร
official (en)Bangkok
official (zh)曼谷
admin codeTH-10
aliases9 attached to this id

Every chip above is the same record. Nothing here is fuzzy — these are stored aliases.

Conversion
Fewer abandoned checkouts

Customers find their address
on the first try.

Thai has no single correct romanisation. Jatujak, Chatuchak and Chatujak are one market; Thonglor and Thong Lo are one street. When search returns nothing, the customer retypes once — then leaves.

We match on how a name sounds, so spellings nobody has written down still land on the right place.

Try itspell it wrong on purpose
you typedJatujak
matchedตลาดนัดจตุจักร
romanisedChatuchak Market
chinese乍都乍周末市场
match typephonetic
confidence 1.00
districtChatuchak

No alias list was consulted —Jatujakisn't stored anywhere. It matched on sound.

The same index powers the dropdown your customers actually see.

Try ittype two or three characters
Reach
Three markets, one integration

Thai, expat and Chinese customers
from the same record.

Chinese-speaking buyers and travellers are a material share of Thai property, retail and tourism revenue — usually served by a second, worse dataset, or by machine translation that renames a district every time it runs.

All three scripts live on the place itself. Set the language once and names, addresses, route steps and region labels follow.

Try itswitch language
place idpl_huaikhwang
nameHuai Khwang
addressRatchadaphisek Rd, Huai Khwang, Bangkok 10310
districtHuai Khwang
provinceBangkok

Same record, same id, three scripts — stored, not translated at request time.

The labels on the map switch with it.

Operations
Fewer failed deliveries

A dropped pin becomes an address
a driver can use.

Your customer shares a location. Your driver needs a road, a khet, a postcode — in Thai, in the postal form, not a transliteration of an English guess. That gap is where redeliveries come from.

Try itclick anywhere on the map
point13.73000, 100.56980
addressSoi Sukhumvit 30, Watthana, Bangkok 10110
district (khet)Watthana
provinceBangkok
postcode10110
nearest placePhrom Phong · 0 m

Click the map to move the pin. The Thai line is the postal form, not a transliteration of the English one.

Planning
ETAs you can promise

Honest travel times.
Turn-by-turn, not a straight line.

Distance, duration and steps over geometry classified for Thai traffic — so the ETA you show a customer and the SLA you sign with a client come from the same numbers.

Try itclick to set B, shift-click for A
Mo ChitSuvarnabhumi Airportrouting…
Catchment
Minutes, not a fixed-radius guess

What can we serve
from here?

A radius on a map is a guess dressed up as data — five kilometres means something different beside an expressway than it does down a soi. These are real Valhalla drive-time contours from our own routing engine: 8, 15, 23 and 30 minutes, computed on the same road network the directions above just routed you across.

Area and place counts per band come straight off the geometry Valhalla returns — a geodesic calculation over the actual polygon, not a cell count from a hand-rolled grid. Move the slider and every number updates from the same contour that's drawn.

Try itdrag to pick a contour, click to move the origin
8 min contour from Asok
8 minloading…
15 minnot loaded
23 minnot loaded
30 minnot loaded

One real Valhalla drive-time contour at a time, at the engine's own resolution. Each budget is its own file, fetched when the slider reaches it and kept in memory after that.

Network load
Derived from road class

Where the load sits.
Not a traffic feed.

Nobody publishes observed traffic volume for Thailand, and this archive publishes less than that: the road layer carries no lane count and no speed limit. What it carries is a classification — motorway, trunk, primary, secondary, tertiary, minor, service — and a oneway flag where somebody tagged one.

So the vehicles on the map are derived from that classification and nothing else. A motorway carries more of them and moves them faster than a soi does because that is what the class implies, not because anything here counted a car. Direction follows the tiles where oneway is set, and splits both ways where it isn't.

It reads well as a network at a glance — which corridors carry a city, where a fleet would concentrate. It reads badly as anything you'd route against, and we won't sell it as one.

Modelledroad class in, vehicles out
Density and speed per road class
classper kmkm/hon screen
motorway2688
trunk2172
primary1748
secondary1237
tertiary830
minor522
service212
roads in frame
vehicles drawn
directiononeway from the tiles, where tagged
observed volumenone — no such field exists

Derived from the road classification and nothing else. The tiles carry no lane count, no speed limit and no vehicle count, so the numbers above are what a class implies, not what a junction does.

Depth
Surveyed heights, not storey guesses

The city has a height.
The tiles already know it.

Unlike the section above, nothing here is modelled. Building footprints in the archive carry render_height, and many of them also carry render_min_height — the floor a volume starts at. The panel counts both, live, off whatever tiles are loaded under the camera.

That second field is why this is worth tilting for. King Power Mahanakhon, at the centre of the frame, arrives as roughly thirty stacked volumes stepping from 270 m to 315 m, which is what produces its pixelated silhouette — a single box extruded to one height would lose it. The pin reads the tallest footprint in frame straight off the record; no number in this section was typed in by hand.

From the tilesheights read, not estimated
footprints in frame
carrying render_height
tallest
median height
stacked volumes
fields usedrender_height, render_min_height

Two attributes on the building layer, extruded as they are. The stacked-volume count is what makes the tilt worth doing: a tower with setbacks arrives as a pile of separate solids, each with its own floor height, and only an extrusion with a real base shows that.

Extensibility
Your geometry, our coordinate space

The map takes your objects.
Not just ours.

Everything above this line is data we hold. This is not: it's a three.js scene handed to the map through a custom WebGL layer, given a model matrix built from one lng/lat, and drawn into the same frame as the buildings.

It's the MapScale mark, 205 m over Lumphini Park, on a mast that touches the grass at 13.7312, 100.5425. Deliberately nothing you could mistake for a building — a floating diamond in two rings is obviously ours, so there's no question about which shape came from the archive and which one we put there.

Drag it, or hold ⌘ and scroll to zoom. It stays on that patch of grass through both, because the anchor is a mercator coordinate rather than a screen position — which is the difference between a 3D object on a map and a picture pinned to a page. It writes into the same depth buffer as the building extrusions, so a tower standing between you and it cuts it off rather than the other way round.

Custom layerthree.js, drawn by the map1,432
What the object is placed by
anchor13.7312 N · 100.5425 E
mercator x, y0.7792847, 0.4614873
one metre, in mercator units2.5716 × 10⁻⁸
height above ground205 m
model matrixtranslate · rotate · scale(1 m)
projectionthe map's own matrix, every frame
occluded bythe buildings' depth buffer

That scale factor is the reason a constant will not do: mercator units are fractions of the projected world, so a metre is worth a different number of them at every latitude. Computed at 13.7312 N, the object stands 205 m tall here — and would stand 205 m tall in Chiang Mai, from the same code with the coordinate changed.

A vehicle at its last ping, a floor plan on its plot, a crane on a site, a coverage volume over a cell tower — same call, more triangles. We'll take the geometry and the coordinate; the camera, the occlusion and the projection are already here.

Hierarchy
Three levels, one id space

Province, district, subdistrict —
and one id that survives all three.

"Show me everything in this province" is the most common question a management team asks a map, and the most expensive to build from scratch. Thai geography nests — 77 provinces, 928 districts beneath them, subdistricts beneath those — and almost every question on that tree lands somewhere a name-keyed dataset breaks the first time a transliteration changes.

Click down through it. Each level is joined to the one above on the administrative code, never on the label — the khet everyone spells Watthana is Vadhana in the source data, and a join on that string would drop it without a single error.

These are the official boundaries. A shape you draw yourself — a delivery zone, a sales territory — is a different query against the same places; tell us the polygon and we'll scope it rather than fake one here.

Try itclick a shape on the map, or a name below
Loading boundaries…
showingdistrict (เขต / อำเภอ)
selectedThailand
pcodeTH

Boundaries: RTSD / UNOCHA COD-AB, published on HDX (CC BY-IGO), vendored as static files and simplified for display — they are not in our own tiles. Levels are joined on the PCODE — the official romanisation of วัฒนา is “Vadhana”, so a join on the English name would drop a district and look like it worked.

The comparison

What you're actually
choosing between.

Global providers are excellent almost everywhere. Thailand is one of the places where "almost" is expensive — and where a local vendor can be held accountable in the same time zone.

Typical global providerMapScale
Thai place namesVaries by dataset and by fieldOfficial Thai on every record
Romanisation variantsExact match, misses on spellingPhonetic, spelling-independent
Chinese namesSparse or machine-translatedStored, reviewed, stable
Admin geometryProvince level, often coarseProvince, amphoe and tambon
BillingPer map load and session, hard to forecastPer call, flat rate
SupportTicket queue, English, offset time zoneThai and English, Bangkok hours
Data residencyVendor's choiceap-southeast-1, contractually
Fixing a wrong nameCommunity edit, weeks to propagateYou report it, we fix the record

Describes common behaviour across global providers rather than a named vendor. Bring us a specific one and we'll benchmark against it with your data.

Commercials

Predictable pricing.
Local accountability.

One rate per call across every endpoint. No per-map-load billing, no session accounting, no invoice that triples the month a campaign works.

Starter
Free100,000 calls / month
  • Every endpoint
  • All three languages
  • Community support
Growth
฿ —per month, volume tiered
  • Support in Thai
  • 99.9% uptime target
  • Bulk address cleaning
  • Named contact
Enterprise
Annualcontracted volume
  • Signed SLA
  • Private region or on-prem
  • Custom regions
  • Quarterly data review
MigrationEndpoints keep the shape your team already integrated against. Run in parallel, compare on your own traffic, cut over when the numbers say so.
Lock-inExport your places, ids and custom regions at any time. Ids are stable, so leaving doesn't corrupt your warehouse.
CompliancePDPA-aligned processing, in-region hosting, and a DPA. Query data is never used to train anything.
ContinuityEscrowed dataset and documented schema, so a vendor risk review has something to read.

Prices shown as placeholders pending the published rate card.

Next step

Start with an audit
of the addresses you already have.

Send a sample export. We come back with the share that resolves cleanly, the failure patterns in your data, and what they're plausibly costing — before anyone signs anything.

Base map