Python automation engineer — web scraping, Telegram bots, self-hosted services.
I build the tools that do the repetitive thing for you, and then keep running when nobody is watching.
- Web scraping that survives contact with real sites — async Playwright with stealth patching, proxy rotation, retries with backoff, and waiting on the data rather than the document.
- Services that run unattended — FastAPI behind a worker queue, graceful shutdown that does not orphan child processes, task state that survives a restart, and systemd units hardened with
ProtectSystem=strict. - Telegram bots for monitoring and notification, on aiogram 3.
- Linux deployment — Arch, systemd, Docker,
ufw, backup scripts. Everything below runs on hardware I maintain myself.
| Project | What it does | Built with |
|---|---|---|
| local-Spotify | Self-hosted music library. Drop in a YouTube link, get back a tagged track with HD cover art, streamable to your phone through Navidrome. Content-hash deduplication, atomic writes, 96 tests in CI. | FastAPI · SQLite · yt-dlp · ffmpeg · systemd |
| price-intelligence | Price monitoring across 133 streetwear and sneaker stores. SKU matching between shops, deal scoring with fake-discount detection, currency normalisation, Telegram alerts. | Python · FastAPI · PostgreSQL · SQLAlchemy |
| universal-web-scraper-template | A scraping starting point I actually reuse: stealth-patched headless Chromium, proxy support, exponential backoff, JSON/CSV output, all from the CLI. 14 tests in CI. | Playwright · BeautifulSoup · asyncio |
| telegram-price-tracker-bot | Watches any element on any page by CSS selector and messages you when its text changes. Watches survive restarts; transient failures retry with backoff, permanent ones fail fast. 48 tests in CI. | aiogram 3 · httpx · SQLite |
| teach-me-english | Offline-first vocabulary trainer on SM-2 spaced repetition. A word carries an example sentence from Tatoeba, an illustration, and a YouTube fragment that plays the exact second the word is spoken. Installs as a PWA, runs as a systemd unit, 42 tests in CI. | PWA · Express · SQLite · service workers |
| vocab-trainer-prototype | Where the trainer above started: three commits in February 2026, ~2 400 lines, no tests and no offline mode. Kept public on purpose — the README tables it against what it became. | Express · SQLite |
| hypr-lock-theme | A monochrome Hyprland lock screen with procedurally generated 4K wallpapers and inline system monitoring. Install, update and uninstall scripts, all with backups. | Shell · Python · Hyprland |
Frontend practice — five Frontend Mentor challenges, all live
Hand-written HTML and CSS, no frameworks. Each repo has a screenshot, a live demo and notes on what the challenge taught.
| Challenge | Demo |
|---|---|
| Product preview card | live |
| Recipe page | live |
| Social links profile | live |
| Blog preview card | live |
| QR code component | live |
Untrusted input gets treated as untrusted — external metadata never reaches the DOM through innerHTML, and host matching is exact so youtube.com.evil.example does not slip through. Failures get separated into transient and permanent, and only the transient ones are retried. Nothing is written into its final location until it has been validated.
Every project above runs its tests in CI, and where a claim appears in a README there is code behind it. When I find a gap between the two, the code moves — not the sentence.
Open to Python and automation roles, and available for freelance scraping, bot and automation work.