FlatRadar — User Guide

Monitor listings across Holland2Stay, OurDomain, OurCampus, Xior and Magis. Get instant notifications and auto-book on Holland2Stay.

Quick Start

1 Docker (recommended for VPS)

cp .env.example .env && mkdir -p data logs logs/caddy
# Edit Caddyfile → replace your.domain.com with your domain
# Edit .env → set WEB_PASSWORD
docker compose up -d

Open https://your.domain.com, log in, then click Start monitor on the Dashboard.

2 macOS

Download the latest .dmg from Releases, drag to Applications, double-click. The browser opens automatically.

3 Windows

Download the latest .zip from Releases, extract and run flatradar.exe.

4 iOS / Android Apps

iOS: Download on the App Store — native SwiftUI client.

Android: Download Android App (.apk) — Kotlin + Compose client with FCM push.

5 Run from source

pip install -r requirements.txt
cp .env.example .env
python web.py

Open http://127.0.0.1:8088.

Supported Platforms

FlatRadar monitors four housing platforms. The Platform badge (H2S / OD / OC / XR) on each listing shows where it came from.

PlatformCoverageData LevelAuto-Booking
Holland2Stay (H2S)26 Dutch citiesUnit (room number, rent, area)✅ Full GraphQL flow
OurDomain (OD)Amsterdam (Diemen + South-East)Unit (#6045, sqm, floor, view)❌ Notify only
OurCampus (OC)Amsterdam Diemen (1 building)Unit (same as OurDomain)❌ Notify only
Xior (XR)30 buildings across 14 Dutch citiesUnit (M1.30.53, sqm, rent, deposit)❌ Notify only
Magis (MG)17 buildings across 5 cities — 9 in EindhovenUnit (rent, sqm, floor, energy label)❌ Notify only
Tip: Go to Settings → Platforms to enable or disable platforms, and Settings → Cities to pick which buildings to monitor.

Web Panel Overview

The web panel is your control center. Everything is accessible from the left sidebar.

Dashboard

At-a-glance view: total listings in database, new listings today, status changes today, last scrape time. Shows the newest listings and recent status changes (48h). Each listing row includes a source badge (H2S / OD / OC / XR).

Click Start monitor to begin scraping. The dot turns green when the monitor is running.

Listings

Browse all listings in the database. Filter by status, city, source (platform), type, max rent, min area, contract, energy, and more. Click any listing to open its detail page on the source platform.

A status may carry a small inferred badge, meaning we worked this status out ourselves — the platform did not report it. Platforms never announce that a unit is gone; they simply stop listing it. So a listing that disappears from the feed is marked Reserved after 30 minutes and Occupied after 2 hours (that is Holland2Stay's own payment deadline). The badge clears the moment the listing shows up again. Always confirm on the platform before acting — an inferred status is our best guess, not a fact.

Map

Listings plotted on an interactive map. Green = available to book, orange = lottery, grey = not available. Markers show platform badges. Requires GOOGLE_MAPS_API_KEY.

The map only shows listings still seen recently — fourteen days by default, adjustable under Map age limit in Settings, or 0 to show everything. "Not available" is a terminal state, so those records stay in the database indefinitely; without this limit, units delisted months ago would remain pinned on the map.

Coordinates are resolved and cached automatically by the monitor — new listings usually appear on the map within half an hour. Admins can also trigger a pass by hand for debugging.

Calendar

Month-by-month calendar showing move-in dates. Filter by city and platform.

Statistics

Charts for 7/30/90-day ranges: new listings trend, status change trend, city & status distributions, rent distribution, platform distribution, listing drop time (NL time).

Setting Up Notifications

Go to Users → click a user → Notifications.

Telegram Cross-platform

  1. Create a bot with @BotFather and copy the token
  2. Send any message to your new bot
  3. Visit https://api.telegram.org/bot<TOKEN>/getUpdates to get your chat ID
  4. Paste the Bot Token and Chat ID into the user form

Email Cross-platform

Two ways; the first is the default.

1. Sent for you (default). Enter a recipient address — no SMTP server needed. You will receive a confirmation email and must click the link in it before delivery begins; that step exists so nobody can sign someone else's address up. The verification state is shown on the user's settings page, where the confirmation can also be re-sent.

2. Your own SMTP. Switch the email mode to custom, then fill in server details:

ProviderSMTP HostPortSecurity
Gmailsmtp.gmail.com587STARTTLS
Outlooksmtp.office365.com587STARTTLS

Use an App Password (not your regular password) if 2FA is enabled. Custom SMTP skips the address verification — delivery is your own server's business.

iMessage macOS only

Enter the recipient's phone number (e.g. +31612345678) or Apple ID email. Only works when the monitor runs on macOS with Messages.app signed in.

WhatsApp Twilio paid

Requires a Twilio account. Fill in Account SID, Auth Token, and the whatsapp:+... numbers.

iOS Push Notifications

If you use the FlatRadar iOS app, APNs push notifications are sent automatically. Notifications are bilingual — Chinese or English depending on your device language.

Android Push Notifications

If you use the FlatRadar Android app, FCM push notifications are sent automatically. Same bilingual support as iOS.

Push and the notifications switch

The notifications switch in a user's settings governs every channel, device push included. Turn it off and the phone stops receiving push.

Granting push permission and signing in from the app turns that switch on for you — agreeing on the phone is agreeing, you do not have to go and click it again in the panel. Turning it off in the panel afterwards is what genuinely turns it off.

Tip: Click Send Test Notification to verify each channel, device push included. The dashboard also shows a checklist whenever an account cannot receive anything, naming the step that is missing.

Auto-Booking (Holland2Stay only)

Go to Users → click a user → Auto Booking.

How it works

When an H2S listing becomes Available to book and matches your filters, the monitor will:

  1. Log into your Holland2Stay account
  2. Create a fresh shopping cart
  3. Add the listing (addNewBooking)
  4. Place the order (placeOrder)
  5. Generate a direct payment link (idealCheckOut)
  6. Send you the payment link immediately

It does NOT auto-pay. You receive the payment URL and complete payment manually.

OurDomain, OurCampus, Xior and Magis are notify-only, for two different reasons. For OurDomain and Xior the booking code is written and reCAPTCHA solving is wired up, but the flow has not been verified end to end, so it is not exposed to users. For OurCampus and Magis the booking flow has never been scouted at all.

Configuration

Safety: Keep Dry run on until verified. Turn off only when ready to place real orders.

Notification Filters

Restrict which listings trigger notifications. Go to Users → click a user → Filters.

FilterExampleApplies toHow it works
Max rent€1200AllOnly listings ≤ €1200/month. Platforms quote different figures — see below
Min area25 m²AllOnly listings ≥ 25 m²
Min floor1AllSkip ground floor (0)
CitiesEindhoven, AmsterdamAllMulti-select — any match
SourcesH2S, ODAllMulti-select — only notify for these platforms
Tenantstudent onlyExcept MagisMulti-select — any match
TypeStudio, 1Except XiorMulti-select — any match
OccupancySingleExcept Xior, MagisMulti-select — any match
FurnishingFurnishedExcept OurCampusMulti-select — any match
ContractIndefiniteHolland2Stay onlyLong-term only (skip short-stay)
Min energy labelBHolland2Stay, MagisOnly listings rated at or above this label
NeighborhoodCentrumHolland2Stay onlyMulti-select; options follow the cities you picked
Offer typeRentHolland2Stay onlyMulti-select — distinguishes rentals from other listing types

All filters are AND together. Leave empty = no restriction.

The Applies to column matters: when a platform does not report a field, the filter is skipped for that platform entirely rather than excluding all of its listings. Setting "Min energy label: B" therefore does not mean everything you receive is rated B — Xior, OurDomain and OurCampus listings never went through that check. The panel labels each filter with the same scope.

What "rent" means per platform

The four platforms do not quote the same number. Read this before setting Max rent:

PlatformPrice shown in the panel and notifications
Holland2StayAll-in — includes service costs and utility prepayment
XiorAll-in — base rent plus that building's registered monthly advance charges
OurDomainBase rent; service costs charged separately
OurCampusBase rent; service costs charged separately
MagisAll-in — base rent plus the service costs printed on each listing

For OurDomain and OurCampus, service costs vary by floor plan and the upstream feed does not say which unit belongs to which plan, so an all-in figure cannot be derived. Those listings carry an asterisk beside the price; hovering shows that building's service-cost range, and the rent line in notifications carries the same note.

What this means for filtering: the same rent ceiling filters what you actually pay on Holland2Stay and Xior, but only the part excluding service costs on OurDomain and OurCampus. Leave headroom for those two, or separate them out with the platform filter.

Global Settings

Go to Settings (admin only).

Polling

SettingDefaultWhat it does
Check interval300s (5 min)Normal polling interval outside peak hours
Peak max interval60sStarting interval during peak (08:30–10:00 NL)
Peak min interval15sFloor — adaptive polling never goes below this
Peak hours08:30–10:00, 13:30–15:00When to accelerate (NL time, weekdays only)
Jitter ratio0.20±20% random variation to avoid detection
Heartbeat interval60 minHow often the admin gets a liveness notification; 0 disables it
Map age limit14 daysMap shows only listings still seen within this many days; 0 shows everything

Platforms & Cities

Enable or disable Holland2Stay, OurDomain, OurCampus and Xior independently. For each platform, select which cities or buildings to monitor. Xior buildings are grouped by city.

After saving, click Apply Now to hot-reload — no restart needed.

Tips & Troubleshooting

Monitor shows "stopped"

Click Start monitor on the Dashboard. If it doesn't start, check Log Viewer or docker compose logs h2s.

No listings appearing

Notifications not arriving

Start at the dashboard. A checklist appears there whenever the account cannot receive anything and names the missing step; if it is gone, the chain is intact. To check by hand:

The notification feed in the panel cannot tell you any of this. It is a site-wide stream, neither per-user nor filtered by your criteria; content in it does not mean your setup works.

403 Blocked (Cloudflare)

If scraping is blocked by Cloudflare WAF:

  1. Set up a residential proxy via HTTPS_PROXY in .env
  2. Restart the monitor to get a new TLS fingerprint
  3. Pause monitoring for a few hours to cool off
Pro tip: The Log Viewer (admin → terminal icon in sidebar) shows Monitor Log (INFO+) and Errors Log (WARNING+) with keyword search, line numbers, and level color highlighting.