Live product · Singapore carparks
Carpark SG
Type where you're going. See the nearest carparks, what they'll actually cost you, and how many lots are free — right now.
What's different
Vs. other SG carpark apps
- ✓Destination-first — you search where you’re going, not a carpark’s name; it does the “what’s near here and cheap” work for you.
- ✓HDB, URA and private operators in one ranked list, rates and live lots together — rather than one source, or one operator’s own app.
- ✓A missing rate is a dead end everywhere else. Here one tap sends an AI to find the operator’s published rate, and the carpark is priced seconds later instead of showing you a blank.
The idea
An itch every SG driver knows
You're heading somewhere, and you have no idea where to park, what it'll cost, or whether there'll be space. The data exists — HDB publishes rates and live availability, URA has its own, private operators post rates on their sites — but it's scattered, inconsistent and often out of date.
Existing apps mostly answer “where are carparks” or “let me pay for parking.” None answered the question I actually had: “I'm going here for 2 hours — where's the nearest, cheapest place to park, and how much will it cost me?” So I built that.
And — let's be honest — there's a very Singaporean motive here too: nobody likes overpaying for parking. Why fork out mall rates when there's an HDB carpark a few minutes' walk away for a fraction of the price? At heart this is a tool for the thrifty (read: stingy) driver who'll happily walk one more block to save a couple of dollars. Kiasu? Maybe. But every dollar saved on parking is a dollar for kopi.
v1
The smallest useful loop
The first version did one thing well: type an address → geocode it with OneMap (Singapore's official map service) → find nearby carparks → rank them by distance. Rates came from the government open datasets; a single SQLite database held everything. No accounts, no install — just a fast page that answered the question.
Along the way
What it grew into
Real walking distance, not crow-flies
“200 m away” is useless if an expressway sits between you and the carpark. I wired in OneMap’s walking routes so distances reflect the actual walk — with a straight-line fallback, clearly labelled “approx”, when routing isn’t available. Later I added the estimated walking time beside it.
A cost, not a rate table
Anyone can show a rate card. The useful answer is “$3.20 for 2 hours starting now.” So I built a fee engine that prices the actual visit — your duration and arrival time, and weekday vs Saturday vs Sunday/public-holiday from the SG holiday calendar. A rate like “7am–5pm & 11pm–7am: $1.50 for the first 30 mins, then $0.05/min; 5pm–11pm: $3.00 per entry” used to be priced with whichever band matched first, so arriving at 6pm was billed per-minute. Bands are now split and matched against when you actually turn up, including ranges that wrap past midnight, and the card shows which one it applied — grace periods and daily caps included.
Live availability, including the carparks that needed it most
The open availability feed covers HDB carparks only — which is precisely the wrong half, because Orchard, Marina and the CBD are served by commercial operators. A second feed (LTA DataMall) fills that gap; since it carries no identifier this app already holds, carparks are matched to it by position within 120 m. If the feed is down or unconfigured it returns nothing rather than throwing: availability is a nicety and must never fail a search.
Is the extra walk worth it?
Every priced carpark is shown relative to the nearest one — “Save $2.40 · 4 min further”, or “+ $2.80 · 1 min further” — so the money and the walk are weighed against each other instead of left as two separate numbers to reconcile in your head.
Filling the rate gaps — the hard part
Government data covers HDB and URA, but thousands of private carparks have no rate in any API. I added three ways to fill a missing rate: an Auto query that searches the web and has an LLM extract the official rate; a “from a link” mode that reads an operator’s page; and a paste mode for JavaScript-heavy sites whose prices never reach the fetched HTML. Search and extraction each run across independent providers — the morning the primary model hit its free-tier cap, the app fell through to the next and kept answering instead of going dark.
Trade-offs
The judgment calls I'm proud of
The interesting decisions weren't features — they were what to do when the data is imperfect, which in Singapore parking is always.
Transparency over false precision
Stale, missing data is the whole problem — so I refused to hide it. Every rate carries its source and age (“URA official · 3 days ago”, “AI-retrieved · verify”), and anything that isn’t a live official API can be re-checked from the web on demand. A number you can judge beats a confident-looking wrong one.
AI as a helper, not an oracle
The model fills gaps no dataset covers, so the guards matter more than the model does. A rate is refused if the fee engine can’t price it — a confident wrong number is worse than a blank, and worse again because the row then counts as covered and nothing retries it. A citation is refused unless the search actually returned that URL: asked for “the most authoritative source”, a model will compose a plausible one, and a fabricated citation makes a rate look better sourced than an honest one. And a rate is refused if the address it quotes sits more than a kilometre from the place you asked about.
Graceful degradation over hard failure
No routing token? Fall back to straight-line distance and say so. No rate on file? Show the carpark anyway and offer to find one. The app should always hand back something useful rather than an error.
Issues faced
The bug that names cause and names cannot catch
Ask for MOE HQ at Evans Road and the app served the Ministry of Education Building's rates, from Buona Vista, 3.5 km away. Ask for Midview Building in Bukit Batok and it served Midview City's, 13 km away. Both times the destination had already been geocoded correctly. The app knew where you meant, and never once compared it against where the rates came from.
The tempting fix is to check that the names match, and here it provably cannot work: both wrong answers share their distinctive word with the right one. Names caused the error, so names cannot detect it. Geography is the independent signal, and the line came from the data rather than from taste: across the correctly filed rates, the widest honest disagreement between a row's own coordinates and the geocode of its own name was 390 m, while the two failures sat at 3.5 km and 13 km. One kilometre lands 2.5× above the worst honest disagreement and 3.5× below the nearest real error.
Fixing that turned up the larger problem. Saved rates were matched to a destination by substring, so a row filed under “MOE” answered for every MOE-prefixed place in Singapore. 149 of 1,146saved rates were resolving to the wrong row: “Orchard Central” to “Central ©”, “Nex Mall” to “KINEX Mall”, TUAS AVE 11, 12 and 13 all to TUAS AVE 1. None of it was visible from the outside, because every one of them returned a perfectly plausible price. Re-pricing all 149 afterwards found no actual mispricings — luck, not design.
Where it is now
Live, and the app I reach for
Carpark SG turns “any Singapore address + how long you'll park” into a ranked, priced, availability-aware list of nearby carparks — directions one tap away, and a rate you can trust because it tells you where the number came from, when it was last true, and refuses to show you one it can't stand behind — arrival-time aware, with live lots now covering the commercial carparks too, and each option priced against the nearest so you can judge whether the extra walk is worth it. It's live, installable to your phone, and it's the app I actually open when I'm the one hunting for a spot.
See it in action
Try a real Singapore address and watch it rank, price and route you to a spot.
Launch the app ↗