An automated, self-hosted job board monitoring system built with Python, Playwright, and SQLite. Job Hunter continuously tracks corporate career pages across global tech enterprises, filters new listings against your personal skill keywords and location preferences, and delivers instant alerts straight to your Telegram device.
- π 9+ Built-in Scraper Engines: Native API clients and DOM parsers for major ATS platforms:
- Greenhouse (JSON API)
- Workday (REST API / Search endpoints)
- Lever (Posting API)
- SmartRecruiters (Public Job API)
- Eightfold AI (API pagination)
- Workable (Board API)
- Phenom People (Careers Search API)
- XML Sitemap Crawler (Automated job link discovery)
- Generic Headless Scraper (Playwright Chromium for dynamic JavaScript single-page apps)
- π― Advanced Multi-Layer Filtering:
- Keyword Include/Exclude: Match relevant roles (e.g.
embedded systems,FPGA,firmware) while filtering out noise (e.g.frontend,sales). - Geographic Filtering: Restrict job postings to selected countries (e.g. Western/Southern Europe) or allow remote/global roles.
- Keyword Include/Exclude: Match relevant roles (e.g.
- π§ Smart Deduplication & History:
- SQLite database persists unique job fingerprints (
url+title+company) so you never get notified twice for the same opening.
- SQLite database persists unique job fingerprints (
- π² Telegram Notifications & Interactive Bot:
- Rich Markdown notifications sent in batches.
- Interactive bot polling: add new companies on the fly using
/add <Company> <URL>directly from Telegram!
- π³ Docker-First & Low Footprint:
- Production-ready Docker Compose container with memory capping (1GB max), non-root user permissions, volume persistence, and automatic healthchecks.
- π 100% Private & Open Source:
- Zero telemetry or 3rd-party tracking. All scraped data and credentials stay on your server.
ββββββββββββββββββββββββββββββββββββββββββββββββ
β APScheduler (Runs every N hours) β
ββββββββββββββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β Scraper Engine Dispatcher (src/) β
ββββββββ¬ββββββββββββββββΌββββββββββββββββ¬ββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ
β ATS APIs (JSON) β β XML Sitemaps β β Playwright Head- β
β Greenhouse/Lever β β Crawler β β less Chromium β
β Workday/Eightfold β β β (JS Dynamic Apps)β
βββββββββββββββ¬βββββ ββββββββ¬ββββββββ βββββ¬βββββββββββββββ
β β β
βββββββββββββββββΌββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β SQLite Database (data/jobs.db) β
β (Deduplication & Fingerprinting) β
ββββββββββββββββββββββββ¬ββββββββββββββββββββββββ
β New jobs only
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β Filter Engine (src/filters.py) β
β (Keyword Include/Exclude & Geo Check) β
ββββββββββββββββββββββββ¬ββββββββββββββββββββββββ
β Matched jobs
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β Telegram Bot API & Interactive Poll β
β - Real-time Notifications β
β - `/add <Company> <URL>` command β
ββββββββββββββββββββββββββββββββββββββββββββββββ
| Engine | Type | Sample URL Format | Description |
|---|---|---|---|
greenhouse |
REST API | https://boards.greenhouse.io/company |
Official Greenhouse Job Board API. |
lever |
REST API | https://jobs.lever.co/company |
Official Lever Postings API. |
workday |
REST API | https://company.wd3.myworkdayjobs.com/... |
Workday external job board API. |
smartrecruiters |
REST API | https://api.smartrecruiters.com/v1/companies/... |
SmartRecruiters public API. |
eightfold |
REST API | https://company.eightfold.ai/careers |
Eightfold AI candidate portal API. |
workable |
REST API | https://apply.workable.com/company/ |
Workable postings API. |
phenom |
REST API | https://careers.company.com/jobs |
Phenom People careers API. |
sitemap |
XML Crawler | https://www.company.com/sitemap.xml |
Parses XML sitemaps for job detail URLs. |
generic |
Headless Browser | https://company.com/careers |
Playwright Chromium engine for SPA/React/Angular career portals. |
- Docker (v20.10+)
- Docker Compose (v2.0+)
git clone https://github.com/your-username/job-hunter.git
cd job-hunterCopy the template environment file:
cp .env.example .envEdit .env to supply your Telegram credentials:
TELEGRAM_BOT_TOKEN=123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ
TELEGRAM_CHAT_ID=987654321
SCAN_INTERVAL_HOURS=6
LOG_LEVEL=INFOHow to create a Telegram Bot:
- Message @BotFather on Telegram and send
/newbot.- Follow the prompt to get your Bot Token.
- Start a chat with your bot, then get your Chat ID by visiting:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates(or use@userinfobot).
Copy the example companies template and edit config/companies.yml to specify the companies and ATS scrapers you wish to monitor:
cp config/companies.example.yml config/companies.ymlExample configuration (config/companies.yml):
companies:
- name: Example Tech
country: Italy
careers_url: https://example.eightfold.ai/careers
scraper: eightfold
company_id: exampletech
- name: NXP Semiconductors
country: Netherlands
careers_url: https://nxp.wd3.myworkdayjobs.com/careers
scraper: workday
company_id: nxp
workday_tenant: nxp
workday_instance: wd3
- name: Exein
careers_url: https://job-boards.eu.greenhouse.io/exeinspa
scraper: greenhouse
company_id: exeinspaCopy the example filters template and edit config/filters.yml to specify desired keywords and allowed locations:
cp config/filters.example.yml config/filters.ymlExample configuration (config/filters.yml):
include_keywords:
- hardware engineer
- embedded systems
- firmware developer
- fpga design
- pcb layout
exclude_keywords:
- frontend developer
- web developer
- sales manager
allowed_countries:
- Italy
- Germany
- Netherlands
- France
- Switzerland# Build the Docker image
docker compose build
# Start in detached (background) mode
docker compose up -dCheck the logs in real time:
docker compose logs -fOnce running, Job Hunter listens for commands in your Telegram chat:
/helpβ Displays available commands and bot status./add <Company Name> <Careers URL>β Dynamically registers a new company toconfig/companies.yml. The bot auto-detects the ATS platform (Workday, Greenhouse, Lever, Eightfold, Workable, Phenom, SmartRecruiters) and includes it in the next scan cycle!
Example:
/add Acme Corp https://boards.greenhouse.io/acmecorp
job-hunter/
βββ Dockerfile # Python 3.12-slim + Playwright Chromium image
βββ docker-compose.yml # Service setup with volume persistence & resource limits
βββ requirements.txt # Dependencies (Playwright, httpx, APScheduler, PyYAML)
βββ .env.example # Environment variables template
βββ config/
β βββ companies.example.yml # Template for target companies config
β βββ filters.example.yml # Template for keyword & location filter rules
β βββ companies.yml # User target companies (ignored by Git)
β βββ filters.yml # User search filters (ignored by Git)
βββ data/
β βββ jobs.db # Persistent SQLite database (auto-created)
βββ src/
β βββ main.py # Entry point
β βββ config.py # Configuration loader & validation
β βββ database.py # SQLite persistence & query operations
β βββ models.py # Data structures (Job model)
β βββ filters.py # Keyword & geographic filtering logic
β βββ telegram.py # Telegram notifications & bot polling engine
β βββ scheduler.py # APScheduler orchestration loop
β βββ scrapers/ # Modular ATS scraper implementations
β βββ base.py
β βββ generic.py
β βββ greenhouse.py
β βββ lever.py
β βββ workday.py
β βββ smartrecruiters.py
β βββ eightfold.py
β βββ workable.py
β βββ phenom.py
β βββ sitemap.py
β βββ registry.py
βββ tests/ # Unit and integration test suite
If you prefer to run Job Hunter natively without Docker:
# Prerequisites: Python 3.12+
python -m venv venv
# On Linux/macOS:
source venv/bin/activate
# On Windows (PowerShell):
.\venv\Scripts\Activate.ps1
# Install requirements
pip install -r requirements.txt
# Install Playwright browser binaries
playwright install chromiumpython -m src.mainJob Hunter comes with a comprehensive test suite covering scrapers, filtering logic, and database operations.
# Run tests
python -m pytest tests/ -v
# Run tests with coverage report
python -m pytest tests/ -v --cov=src --cov-report=term-missingYou can host Job Hunter 24/7 on any cheap Linux VPS (Hetzner, DigitalOcean, AWS EC2, Linode, Scaleway).
# 1. Update system & install Docker
sudo apt update && sudo apt install -y docker.io docker-compose-plugin git
# 2. Clone repository to /opt
sudo git clone https://github.com/your-username/job-hunter.git /opt/job-hunter
cd /opt/job-hunter
# 3. Configure env & config files
cp .env.example .env
nano .env
# 4. Start Docker container
docker compose build
docker compose up -d
# 5. Enable autostart on boot
sudo systemctl enable dockerAll jobs are tracked in data/jobs.db. The SQLite database is mounted outside the container for seamless data persistence.
# Query recent jobs via sqlite3
sqlite3 data/jobs.db "SELECT company, title, location, first_seen_at FROM jobs ORDER BY first_seen_at DESC LIMIT 10;"
# Count discovered jobs per company
sqlite3 data/jobs.db "SELECT company, COUNT(*) FROM jobs GROUP BY company ORDER BY COUNT(*) DESC;"# Backup SQLite database
cp data/jobs.db "data/jobs_backup_$(date +%Y%m%d).db"Job Hunter's scraper architecture is modular and extensible. To add support for a new ATS or career site platform:
- Create a new file in
src/scrapers/my_platform.py:
from src.models import Job
from src.scrapers.base import BaseScraper
class MyPlatformScraper(BaseScraper):
def scrape(self) -> list[Job]:
# Implement fetching & parsing logic
jobs = []
# ... fetch jobs ...
return jobs- Register your class in
src/scrapers/registry.py:
from src.scrapers.my_platform import MyPlatformScraper
# Add to _get_scrapers() dictionary:
"my_platform": MyPlatformScraper,- Specify
scraper: my_platforminconfig/companies.yml.
- No Third-Party Analytics: Job Hunter sends data only to the official Telegram Bot API endpoint (
https://api.telegram.org). - Secrets & Configuration Protection:
.env, custom configuration files (config/companies.yml,config/filters.yml), and SQLite database files (data/*.db) are explicitly ignored by Git (.gitignore). - Least Privilege: The Docker container executes under a non-root system user (
appuser).
Distributed under the MIT License. See LICENSE for more information.