โ† All guides Reference ยท 12 min

Every bot library, grouped by the job it does

Libraries get compared in flat lists that mix tools doing completely different jobs. Here they're grouped by function, so you can see what's actually an alternative to what.

Nearly every bot is assembled from the same eight groups. Pick one tool from each group you need and you have a working system. The mistake is comparing across groups โ€” a fetcher isn't an alternative to a parser.

1. Fetching โ€” getting bytes from a server

ToolLanguageReach for it when
requestsPythonThe default. Synchronous, readable, everywhere.
httpxPythonYou need async, HTTP/2, or to fetch hundreds of URLs concurrently.
aiohttpPythonYou're already in an asyncio codebase.
curl-cffiPythonA site fingerprints TLS handshakes and blocks ordinary clients.
fetch / undiciJavaScriptYou're in Node. fetch is built in now.

Start with requests. Move to httpx only when concurrency is the actual bottleneck โ€” which is later than you think.

2. Parsing โ€” finding things inside HTML

ToolLanguageReach for it when
BeautifulSoupPythonThe default. Tolerant of malformed HTML, pleasant API.
lxmlPythonSpeed matters, or you want real XPath. Also BeautifulSoup's best engine.
selectolaxPythonParsing at serious volume; noticeably faster than both.
CheerioJavaScriptNode, and you want jQuery-style selectors.

Install lxml alongside BeautifulSoup and pass "lxml" as the parser โ€” same API, considerably faster than the built-in one.

3. Driving a browser โ€” when the page needs to run

ToolReach for it when
PlaywrightThe default for new work. Auto-waiting removes most flakiness; clean multi-context support; Python, JS, .NET, Java.
SeleniumExisting Selenium codebase, Selenium Grid, or a language where it's better supported.
PuppeteerNode-only projects, Chrome-only. Playwright grew out of this lineage.
Patchright / undetected driversA site actively detects automation. Understand the terms you're agreeing to before you go here.

Every tool in this group is roughly a hundred times more expensive per page than groups 1 and 2. Confirm you need it.

4. Crawling โ€” many pages, politely

ToolReach for it when
ScrapyThousands of pages. Gives you scheduling, retries, throttling, deduplication and pipelines for free.
CrawleeSame idea in Node/Python, with browser and HTTP crawling under one API.
Your own queueUnder a few hundred pages. A list, a set of seen URLs and a sleep is genuinely enough.

5. Scheduling โ€” making it run without you

ToolReach for it when
cronA machine that's reliably on. Remember it doesn't inherit your shell's environment variables โ€” the classic silent failure.
GitHub Actions (schedule)Free, always on, versioned. Excellent for anything hourly or slower.
systemd timersA Linux box or a Raspberry Pi you control, and you want restart-on-failure.
APScheduler / Celery beatScheduling belongs inside a long-running Python application.

6. Talking to platforms

PlatformLibraryNote
Telegrampython-telegram-botEasiest platform to start on โ€” a token from @BotFather and you're live.
Discorddiscord.pyMature. Mind the gateway intents, which trip everyone up once.
Slackslack-boltSocket Mode saves you exposing a public URL.
WhatsAppCloud API / TwilioRequires business verification and template approval. Budget days, not hours.
Emailimaplib / Gmail APIIMAP for reading anything; the Gmail API when you need labels and threading.
AnywhereA plain webhookOften all you need. Don't add an SDK for one HTTP POST.

7. Storing what you collected

ToolReach for it when
SQLiteAlmost always, to start. One file, no server, handles millions of rows, ships with Python.
CSV / ParquetThe output is a dataset for someone else. Parquet once it's large.
PostgresSeveral things write concurrently, or you've outgrown one file.
pandasCleaning and reshaping between scrape and storage.

Store the raw response as well as the parsed fields. When a selector breaks, the original page is what lets you fix it quickly.

8. Staying unblocked

Before any tooling: a real User-Agent that identifies you and offers a contact, a deliberate delay between requests, honouring robots.txt, and caching so you never fetch the same page twice. That alone keeps most well-behaved scrapers welcome.

Beyond that sit rotating proxies, residential IP pools and CAPTCHA-solving services. They exist, they work, and they're also the point at which you're actively circumventing a site's stated wishes โ€” which changes the ethical and sometimes legal position. Worth being deliberate rather than drifting there.

Two starter stacks

Watch a few pages for changes: requests + BeautifulSoup + lxml + SQLite + GitHub Actions. Free to run, finishes in an evening. That's exactly the change watcher.

Scrape a JavaScript-heavy site: check the Network tab for a JSON endpoint first; if there isn't one, Playwright + SQLite. That build sheet walks both routes.

The general rule across every group: start with the simplest tool that could work, run it against real data, and let it break. What breaks tells you which of these you actually needed โ€” and it's usually fewer than you'd have picked up front.

One new build sheet a week

Guides like this one, plus a new build sheet every Thursday. Written by a person who built it.