Project website: https://sc0vu.github.io/funda-cli/ (GitHub Pages; see site/README.md for setup).
A lightweight local CLI for personal Dutch housing research.
The first version deliberately separates three concerns:
- Discovery — read listing URLs from Funda sitemaps.
- Enrichment — optionally fetch structured details through an adapter.
- Search — query a local SQLite database without repeatedly hitting a remote service.
The bundled enrichment adapter calls Funda API, thanks for pyfunda. Funda does not provide a public consumer developer API; internal endpoints may change and use may be subject to Funda's terms. Keep request volume low and use this for personal research.
- Go 1.25+
go mod tidy
go build -o funda ./cmd/fundaDiscover rental listings from the sitemap using a browser-profile Go HTTP client:
./funda sync --category rent --profile chromeAvailable profiles are chrome, firefox, safari, edge, ios, and chrome_android. The transport reproduces browser-like TLS/HTTP behavior, but the CLI does not implement CAPTCHA/challenge solving, proxy rotation, or retries intended to defeat an explicit access restriction.
Review the references discovered by the sitemap with the same search command used for enriched listings:
./funda search --city utrecht --category rentOnly show references that do not have detail data yet:
./funda search --city utrecht --category rent --unfetchedShow the full Funda URL as well:
./funda search --unfetched --urlUnfetched rows show - for price, area, bedrooms, and energy label. These fields become available after detail enrichment.
Enrich a small batch:
./funda enrich --city utrecht --category rent --limit 20Now search locally by structured fields:
./funda search \
--city utrecht \
--category rent \
--max-price 2200 \
--min-area 50 \
--fetchedView one listing:
./funda view 12345678Default database: ./funda.db
Change it with:
export FUNDA_DB="$HOME/.local/share/funda/funda.db"Tables:
listing_refs sitemap-discovered IDs, URLs, city, category, lastmod
listings API-enriched price, area, rooms, energy label, etc.
The CLI does not make a remote search request every time you type funda search.
The normal workflow is:
sitemap -> listing_refs -> optional detail enrichment -> SQLite -> local search
This makes the user-facing search fast and keeps remote requests explicit and cacheable.
- Throttle the request.
- Detect changed sitemap
lastmodvalues and refresh only stale details. - Add
--refreshtosearch/view. - Add JSON output for shell pipelines.
- Add saved searches and favorites.
- Add a Bubble Tea TUI.
- Add provider abstraction for other Dutch housing sources.
MVGM / ikwilhuren.nu support has been added. See MVGM.md.
funda sync --source mvgm --city utrecht
funda enrich --source mvgm --city utrecht --limit 50
funda search --source mvgm --city utrecht --fetched --income 60000 --savings 50000Fetched listings with latitude/longitude can be rendered as a Unicode Braille map using live OpenStreetMap data from the Overpass API:
./funda map --source funda 12345678
./funda map --source mvgm --radius 800 --width 100 --height 30 some-listing-id
./funda view --source funda --map 12345678The renderer requests nearby roads, buildings, waterways, water, parks, and grass areas and rasterizes their real OSM geometry into a 2x4-dot Braille canvas per terminal cell. The property is marked by a cross at the center. --radius is in meters. Map rendering requires network access; normal local search/view behavior remains offline unless --map or the map command is used.
Funda CLI includes two local games, each supporting buy and rent:
- Guess the Price: Estimate the advertised asking price or monthly rent. Prices and source listing URLs are hidden until you submit your guess. Optional Detective hints cost 100 points.
- House Hunter: Explore cached properties, schedule viewings, perform fictional inspections, and make simulated buying offers or rental applications. No real offers or applications are sent.
Games use enriched listings already stored in the local SQLite database. Run sync and enrich first; games do not fetch fresh property data.
# Five-round guessing games
./funda game guess --mode buy --city utrecht
./funda game guess --mode rent --city utrecht --detective
# Daily guessing challenges (UTC-based seed)
./funda game guess --mode buy --city utrecht --daily
./funda game guess --mode rent --city utrecht --daily
# House Hunter: buying and renting
./funda game hunter --mode buy --city utrecht --budget 375000
./funda game hunter --mode rent --city utrecht --income 4500 --income-multiplier 3--daily generates a deterministic seed from the UTC date, city, game, and mode. This does not guarantee identical properties for different players: rounds are selected from each player's local database. Scores should only be compared when datasets match. There is no online leaderboard or globally synchronized daily challenge.
Completed game results are saved to a local history file by default. House Hunter also checkpoints progress so you can quit and resume later.
./funda game hunter --mode buy --city utrecht
./funda game hunter --mode buy --city utrecht --resume
./funda game hunter --mode buy --city utrecht --restart
# Disable local saving, or override its location
./funda game guess --mode buy --no-save
./funda game guess --mode buy --history-file ./game-history.json
./funda game hunter --mode buy --save-file ./hunter-save.jsonThe default history location is ~/.local/share/funda/game-history.json on Linux, ~/Library/Application Support/funda/game-history.json on macOS, and %AppData%\funda\game-history.json on Windows. House Hunter saves beside the default history file. Resume validates the saved property sequence and asking prices; if the local database has changed, restart the game instead.
In House Hunter, use v for viewing, i for a fictional inspection, e for cached details, a for a simulated bid/application, s to skip, and o to open the original listing in a browser. The simulation has a 20-turn limit.
Optional photo URLs can be supplied using --photos-file; the game currently displays links, not native inline photos. --image-mode auto|kitty|iterm2|link|none selects the image capability preference, but actual inline listing-image integration is not yet implemented. Automatic photo extraction is deferred.
go test ./...
go test -race ./...
go build -o funda ./cmd/fundaInspections, rival bids, and rental-selection outcomes are fictional. They must not be used to assess actual property condition, valuation, or application chances. The complete application test suite still requires verification in the project's configured Go environment. See GAMES.md for more details and RELEASE_CANDIDATE.md for release status.
The check and watch commands fetch/sync source listings, refresh missing or stale
property details, match configured watches and deliver notifications. They use the
same SQLite database as the existing CLI. Configuration is JSON (see
examples/monitor.json). Environment variables hold credentials; do not store
Telegram bot tokens in the config file.
export TELEGRAM_BOT_TOKEN='...'
export TELEGRAM_CHAT_ID='...'
funda notify test --config examples/monitor.json --provider telegram_personal
funda check --config examples/monitor.json
funda watch --config examples/monitor.jsonUse funda check from cron or a systemd timer; watch is a long-running
process. Do not run concurrent checks against the same database. The first
successful check establishes a baseline when notify_existing is false. Each
watch can name multiple providers, and delivery status is stored per
watch/property/provider. Supported providers: Telegram and HTTPS JSON webhook.
SMTP/email is planned, not yet implemented. A check refreshes up to
enrich_limit missing/stale properties per watch, so a large initial backfill
may require several checks. The crawler relies on source visibility and cannot
guarantee immediate discovery. Check source terms and permitted reuse before
running a public alert service.
Example cron entry (adjust binary and config paths):
*/10 * * * * /usr/local/bin/funda check --config /home/user/.config/funda/monitor.json