DEV.to Scraper
Scrape DEV.to articles by tag, author or sort. Fields: title, URL, tags, reactions, comments, reading time, cover image, full body. $2.00 per 1,000 articles.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
tag,username,topDays(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.002 per article = $2 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Article returned | Charged per article returned. | $0.002 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-06-13, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
tag | Only return articles with this DEV.to tag (e.g. "javascript", "react", "webdev"). Leave empty to not filter by tag. | string |
username | Only return articles by this DEV.to author username (e.g. "ben"). Leave empty to not filter by author. Use it with Sort by = Latest and no tag: DEV ignores the author when a tag is set, and ignores Top and Rising for an author, so those inputs are refused before anything is fetched. | string |
topDays | When Sort by = Top, return the highest-reaction articles published within the last this many days (e.g. 7 = top of the past week, 365 = top of the past year). Ignored for Latest/Rising. | integer |
sortBy | How to order/select articles. "top" = most reactions in the last N days (see Top days), "latest" = newest first, "rising" = currently rising. Rising works only with no tag and no author. For an author, use Latest. With a tag, Latest gives DEV's current listing for that tag, not a strict date order. | string |
minReactions | Only return articles with at least this many reactions. Leave empty for no minimum. DEV has no such filter, so the run reads its pages and keeps the articles that pass; the rest are not charged. A strict minimum can return fewer articles than Max articles, because a run reads at most 5 pages more than it would without one. | integer |
minComments | Only return articles with at least this many comments. Leave empty for no minimum. Works like Minimum reactions, and the two can be combined. | integer |
maxItems | Maximum number of articles to return. The actor paginates the API (100 per page) until this many are collected or the results run out. | integer |
includeBody | Fetch the full article body (markdown/HTML) for each result via a second API call per article. Slower and makes more requests. | boolean |
notionConnector | Optional. Write each article as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless. | string |
notionParentId | Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead. | string |
What you get
A structured dataset — each result includes fields like:
titleauthortagsreactionscommentsurlExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Developer & Research Tools
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
Wikidata Scraper
Search Wikidata for people, companies, places, books or films. Get the ID, the name, other names, a description and the Wikipedia link. $0.20 per 1,000.
Domain Inspector
Check many domains at once. Get DNS, WHOIS registrar and expiry, TLS dates, redirects, security headers, robots and tech. $1.50 per 1,000.
GitHub Scraper
Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.
Stack Overflow / Stack Exchange Scraper
Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.
Package Registry Scraper (npm + PyPI)
Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.
arXiv Scraper
Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.
Where this tool sits
- Categories
- Developer & Research Tools
DEV.to Scraper: articles by tag, author or reaction count, with no API key
Pick a tag, an author, or neither, and get DEV.to articles back as rows: title, summary, tags, reaction count, comment count, reading time, cover image and the link. It reads DEV's own public API, so there is nothing to sign up for.
The article body is off by default. You get the summary DEV shows in a card, and you turn on Include full body when you want the whole post, which costs a second request per article.
| Input | A tag, an author username, a sort order, or any combination |
| Output | One row per article |
| Ceiling | 1,000 articles per run |
| Account needed | None, and no API key |
| Price | $2.00 per 1,000 articles, flat on every plan |
📝 What DEV.to Scraper does
It queries DEV's public article listing and pages through it, 100 at a time, until it has the number you asked for or the results run out. Duplicate article ids are dropped.
Three orders are available. Top returns the most-reacted articles published in the last topDays, which is the one to use for finding what actually landed. Latest is newest first. Rising is what DEV currently considers gaining traction, across the whole site.
Filter by tag or by username, or by neither for the site-wide list. Not both at once: DEV reads only the tag when an author is set too, so that input is refused instead of charging you for other people's articles. An author goes with Latest, because DEV lists one author's articles newest first and ignores Top and Rising for them.
📥 What you give it
{
"tag": "javascript",
"sortBy": "top",
"topDays": 7,
"maxItems": 50,
"includeBody": false
}
| Field | Default | What it is |
|---|---|---|
tag | box starts at javascript | One DEV tag, like react or webdev. Case does not matter, it is lowercased for you. Leave empty for no tag filter. |
username | none | One DEV author username, like ben. Leave empty for no author filter. Use it with sortBy set to latest and no tag; other combinations are refused, since DEV ignores them. |
sortBy | top | top, latest or rising. rising only works with no tag and no author. |
topDays | 7 | With top, how far back to look, 1 to 3,650 days. Ignored on the other two orders. |
minReactions | none | Keep only articles with at least this many reactions. DEV has no such filter, so the run reads its pages and keeps the ones that pass. Articles left out are not charged. |
minComments | none | The same for comments. Set both and an article has to clear both. |
maxItems | 50 | Articles to return, up to 1,000. |
includeBody | false | Fetch the whole article text as well. One extra request per article, so a big run takes noticeably longer. |
notionConnector | none | Optional. Write every article into your own Notion as well as the dataset. |
notionParentId | none | Optional. The Notion data source ID to write into. |
proxyConfiguration | off | Optional, and off by default because a normal run does not need it. |
For an author, set sortBy to latest. DEV lists one author's articles newest first, whatever their age, and ignores the Top window. Left on the default top, the run stops with a free BAD_INPUT row rather than charge you for articles outside the window you asked for.
A strict minimum can return fewer rows than maxItems. The run reads at most five pages more than it would without one, then stops with what passed.
📤 What you get back
A real row from a recent run:
{
"ok": true,
"id": 4602684,
"title": "So You've Got a Technical Interview in 7 days...",
"description": "So you got head-hunted. A recruiter from a large company wanted to talk to you about a React...",
"url": "https://dev.to/cathylai/so-youve-got-a-technical-interview-in-7-days-22g5",
"author": "Cathy Lai",
"authorUsername": "cathylai",
"tags": ["react", "career", "javascript"],
"reactions": 9,
"comments": 2,
"readingTimeMinutes": 2,
"coverImage": null,
"publishedAt": "2026-09-09T05:18:13Z"
}
| Field | What it is |
|---|---|
id | DEV's own article id. Stable, so use it to dedupe across runs. |
description | The card summary DEV shows in a listing, not the article. |
body | Present only when includeBody is on. The article as markdown or HTML. null when that second request did not come back. |
tags | Every tag on the article, not just the one you filtered by. |
reactions, comments, readingTimeMinutes | Counts as DEV reports them. A missing value arrives as 0 rather than null, so a genuine zero and a missing field look the same. |
coverImage | The header image URL, or null when the author set none. |
publishedAt | A real ISO timestamp, or null when DEV did not give one. |
url, authorUsername | Empty strings rather than null when DEV omits them, which is rare. |
🧾 Reading the output
Two kinds of row can land in your dataset.
| Row | How to spot it | Charged |
|---|---|---|
| An article | ok: true and an id | yes |
| A diagnostic | ok: false and an errorCode | no |
| Code | What it means |
|---|---|
NO_RESULTS | Nothing matched that tag, author, order and window, or nothing read met your minimum. Widen topDays, lower the minimum or drop a filter. |
BAD_INPUT | The input combines filters DEV ignores together, such as a tag with an author, or a minimum is not a whole number of 0 or more. Nothing was fetched or charged; the row's note says what to change. |
NOT_FOUND | DEV answered 404 for the listing asked for. Check the username spelling. |
RATE_LIMITED | DEV asked for a slower pace. Re-run with a smaller maxItems. |
SERVER_ERROR | DEV answered with a server error. Usually passes on its own. |
BLOCKED | DEV would not serve the listing this time. |
NETWORK | DEV could not be reached. |
The diagnostic row echoes the tag, username, sortBy and topDays you ran with, which makes it obvious when an empty result is a filter problem rather than an outage.
The default table view hides publishedAt and body. Switch to All fields or export as JSON when you need either.
▶️ How to run it
1. Open DEV.to Scraper and click Try for free. 2. Put a tag into Tag, or an author into Author username, or leave both empty. 3. Pick a Sort by. On top, set Top days to the window you care about. For an author, pick latest. 4. Set Max articles, tick Include full body if you want the text, then click Start. 5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost?
$2.00 per 1,000 articles, which is $0.002 each. Flat on every Apify plan, no volume tiers.
You pay per article row delivered. Duplicates are dropped before they reach you, diagnostic rows are not charged, and if nothing matches, no rows are charged. Articles below your minimum are left out and not charged either.
One thing to know before you turn includeBody on: an article whose body request did not come back still arrives as a row, with body set to null, and still counts. Check for nulls if you are relying on the text.
💡 What people use it for
- Finding what actually resonated in a tag this week, with
sortByontopandtopDaysat 7. - Pulling an author's whole catalogue for a reading list or a newsletter.
- Watching a niche tag on a schedule with
minReactionsset, so only what clears your bar arrives. - Collecting full article text on a topic with
includeBody, for search or summarisation.
🚧 What it does not do
- No body by default. Turn
includeBodyon and expect the run to take longer. - No comments text. You get the count, not what anybody wrote.
- No reaction breakdown. One total, not hearts against unicorns against bookmarks.
- No series, no organisation feeds, no followers, no reading lists.
latestwith a tag is not sorted by date. DEV ignores the newest-first request when a tag is
set and sends the tag's current listing in its own order. On a busy tag that is roughly the last day of articles. Sort the rows on publishedAt if the order matters. With an author, latest is newest first.
- No tag and author together, and no Rising for a tag or an author. DEV's listing reads only one
of them, so those inputs are refused, free.
- A missing count reads as
0. There is no way to tell a genuine zero from a field DEV left out. - Nothing older than the window on
top.topDaysis the whole search space for that order. - 1,000 articles per run. For more, narrow by tag and run several times.
🧭 Which content scraper do you need?
| If you want | Use |
|---|---|
| DEV.to articles by tag or author | This one |
| Wikipedia search results or article text | Wikipedia Scraper |
| Research preprints with abstracts and PDFs | arXiv Scraper |
| Product launches and their upvotes | Product Hunt Scraper |
| Repository and developer data from GitHub | GitHub Scraper |
❓ Questions people ask
Do I need a DEV account or an API key? No. The listing API is public.
Why was my author run refused? DEV ignores Top and Rising for an author, and ignores the author when a tag is set too. Clear the tag and set sortBy to latest.
How do I get the article text? Tick Include full body. It adds one request per article.
Can I filter by more than one tag? Not in one run. DEV's listing takes a single tag, so run it once per tag and join the rows on id.
Can I schedule it? Yes. A daily latest run on a tag, deduped on id, keeps a feed current.
Is scraping DEV.to legal? These are public articles served by DEV's own public API. Author names are personal data, which GDPR and similar laws cover, so have a reason for collecting it, and check DEV's terms for reuse of the text. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the run ID and the tag, username and sort you used. The errorCode on the diagnostic row usually names the problem on its own.