Skip to content

About

Real-time Kamernet rental radar with LLM-powered scoring and notifications anywhere (Apprise, Discord, Telegram, ntfy, email, WhatsApp, +100 more). Self-hostable, Docker-ready, optional Next.js dashboard.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

πŸ“‘ Kamernet Radar

Real-time Kamernet rental listing scraper with LLM-powered scoring and notifications anywhere.

Python 3.10+ License: MIT Next.js 16 Docker ready Apprise-powered

Self-hostable. Not affiliated with Kamernet B.V. Educational / personal use.


Finding a place to rent on Kamernet.nl is brutal. Good listings vanish in minutes. Kamernet Radar watches the site for you, scores each new listing against your preferences with a local or free LLM, and pings you the moment something good drops. Choose Discord, Telegram, WhatsApp, ntfy, email, Slack, or any of 100+ other channels.

"I set it up in five minutes and had a notification for a good €1450 studio on my phone within an hour. Would recommend."
β€” every user, eventually, hopefully

What it does

  • πŸ” Polite, robots.txt-compliant scraping. Public HTML pages only, rate-limited, with a transparent User-Agent.
  • πŸ€– LLM scoring 0–100 via OpenRouter (free models work). Rubrics live in editable YAML.
  • πŸ“¬ Notify anywhere. Native Discord rich embeds, Telegram with a password-gated subscriber flow, or Apprise for 100+ channels.
  • 🎯 Preset profiles. student-amsterdam, young-professional-randstad, family-utrecht, generic. Copy and tweak.
  • πŸ“Š Optional Next.js dashboard. Filter, sort, chart, and drill into listings. Runs locally.
  • 🐳 Docker-first. docker compose up and you're running.
  • πŸ—ƒοΈ Postgres-backed. Full listing history, price snapshots, scrape audit log.

Quick start

Option A: Docker (recommended)
git clone https://github.com/jasp-nerd/kamernet-radar
cd kamernet-radar
cp .env.example .env               # edit at least APPRISE_URLS or DISCORD_WEBHOOK_URL
docker compose up -d db            # start Postgres
docker compose run --rm scraper init-db   # one-time schema bootstrap
docker compose up scraper          # start scraping

Want the dashboard too?

docker compose --profile dashboard up
# β†’ http://127.0.0.1:3000
Option B: Terminal only (no Docker)

Requires Python 3.10+ and access to a Postgres instance.

git clone https://github.com/jasp-nerd/kamernet-radar
cd kamernet-radar

# One-time: install uv (https://docs.astral.sh/uv/getting-started/installation/)
uv sync                            # creates .venv, installs from uv.lock

cp .env.example .env               # edit DATABASE_URL + one notification channel
uv run python -m radar init-db     # run schema.sql
uv run python -m radar run         # scrape forever

One-shot dry-run (skips notifications and DB writes, handy for tuning your profile):

uv run python -m radar run --once --dry-run --profile student-amsterdam

Prefer plain pip? pip install . works β€” pyproject.toml declares the same dependencies.

Option C: No notifications, database only

Leave every notifier env var blank. The scraper writes to Postgres silently. Pair it with the dashboard for a private searchable archive.

Configuration

Environment variables (or .env) control behavior. Full list with comments: .env.example.

Variable Required Purpose
DATABASE_URL βœ–οΈ Postgres connection. Without it, no persistence.
PROFILE βœ–οΈ Profile name (default: generic).
OPENROUTER_API_KEY βœ–οΈ Enables AI scoring. Free tier works fine.
DISCORD_WEBHOOK_URL βœ–οΈ Native Discord rich-embed notifications.
TELEGRAM_BOT_TOKEN + TELEGRAM_PASSWORD βœ–οΈ Telegram bot with /start <password> subscription.
APPRISE_URLS βœ–οΈ Any of 100+ channels (Slack, ntfy, WhatsApp, email, Pushover).
CHECK_INTERVAL_MIN/MAX βœ–οΈ Seconds between checks (randomized, default 50-70).

Configure at least one notification channel, otherwise listings go to the database silently. None are required.

Scoring profiles

A profile controls two things: what gets scraped (city, radius, price cap) and how the LLM scores listings. Four ship out of the box:

Profile Who it's for
generic Neutral universal defaults. Start here.
student-amsterdam Two students/young adults near VU Amsterdam, budget ~€2000/mo.
young-professional-randstad Solo professional, €1800–2500, Randstad-wide.
family-utrecht Family of 4, Utrecht + suburbs, 2+ bedrooms, long-term only.

Writing your own takes two minutes of YAML. See docs/PROFILES.md.

Notifications

Pick any channel. The scraper fans out to all configured notifiers:

  • πŸ”΅ Discord. Rich embeds with images, price, availability, AI score. Set DISCORD_WEBHOOK_URL.
  • ✈️ Telegram. Personal bot with password-gated subscriptions. Users send /start <password>. Set TELEGRAM_BOT_TOKEN + TELEGRAM_PASSWORD.
  • 🌈 Apprise. One env var, 100+ channels: Slack, ntfy, email, WhatsApp (via Twilio), Pushover, Matrix, Home Assistant, and more. Set APPRISE_URLS.

All three can coexist. A high-scoring listing fans out to each configured channel. Channel recipes live in docs/NOTIFICATIONS.md.

Dashboard

The optional Next.js dashboard shows listing history, trends, top-scored picks, and landlord leaderboards. Run it locally with npm run dev or docker compose --profile dashboard up. See dashboard/README.md.

Deployment

Local use needs nothing beyond the quick-start. To run Radar 24/7 on a tiny VPS (€4/mo is plenty), read docs/DEPLOYMENT.md. It covers docker compose on a plain VPS, Coolify, Railway, and fly.io.

Related projects

  • πŸ€– kamernet-mcp β€” MCP server that puts Kamernet search inside Claude, Cursor, Codex, or any AI agent. Radar watches and notifies in the background; kamernet-mcp lets you search, read, and rank listings interactively from a chat. They pair well: get pinged by Radar, then dig into the listing with your agent. Install with claude mcp add kamernet -- uvx kamernet-mcp.

Contributing

Pull requests welcome. Especially valuable:

  • πŸ“ New preset profiles. Your city or situation isn't covered? Copy profiles/generic.yaml and send a PR.
  • 🌐 Notification recipes. Add Apprise recipes for channels we haven't covered.
  • 🧭 Provider plugins. Abstract the scraper to target Pararius, Funda, or HousingAnywhere.
  • 🎨 Dashboard polish. Map view, websocket live updates, browser extension.

See CONTRIBUTING.md for dev setup and the roadmap.

Legal & ethical notice

This project is not affiliated with Kamernet B.V. Use it for personal, educational, non-commercial purposes.

  • The scraper respects Kamernet's robots.txt. It hits the public HTML search pages and avoids the disallowed API endpoints (/SearchRooms/GetRooms, /ajax/, etc.). Pull requests that weaken this get rejected.
  • The scraper rate-limits requests with jittered intervals (default 50–70s).
  • You are responsible for complying with Kamernet's Terms of Service and applicable law (including EU GDPR if you process personal data).
  • Use a transparent User-Agent with a link back to this repo (default template in .env.example).

If you're on the Kamernet operations team and this causes trouble, open an issue and let's talk. One HTML fetch per minute per user puts less pressure on your servers than a motivated human refreshing the site.

License

MIT. Do whatever you want, no warranty.

About

Real-time Kamernet rental radar with LLM-powered scoring and notifications anywhere (Apprise, Discord, Telegram, ntfy, email, WhatsApp, +100 more). Self-hostable, Docker-ready, optional Next.js dashboard.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages