How to scrape stackoverflow
Extract Stack Overflow question title, vote score, answer count, tags, view count and accepted-answer flag as schema-validated JSON from one URL.
- Site:
- stackoverflow.com
- Difficulty:
- Easy
- Rendering:
- Static HTML
- Anti-bot:
- Cloudflare, rate-limiting on rapid sequential requests, occasional human-verification interstitial under heavy automated traffic
What you can extract from stackoverflow
These are the fields teams most often pull from stackoverflow.com, and why a hand-written selector for each one tends to break over time.
| Field | Type | Why selectors break |
|---|---|---|
| title | string | The question title lives in an h1 whose anchor class and surrounding header markup get reshuffled in Stack Overflow's frequent UI refreshes, so a hardcoded selector like .question-hyperlink can silently return an empty string after a redesign or grab the edit-link text instead of the clean title. |
| score | number | The vote score sits in a vote-count element that is shared by the question and every answer on the page, so a naive selector matches multiple nodes and you can scrape an answer's score by mistake; the value is also upvotes minus downvotes and may be negative, which trips parsers that assume a non-negative integer. |
| answer_count | number | The answer count appears both in the page header status block and as a heading above the answer list (for example '12 Answers'), so a selector can match the wrong copy, and the heading text mixes the number with the word 'Answers' plus possible 'sorted by' controls that you must strip before casting to a number. |
| tags | array | Tags render as a list of anchor chips whose wrapper class names change between the question summary and the post footer, and the same .post-tag class is reused inside answers and the sidebar 'related tags', so an unscoped selector pulls in tags that do not belong to this question. |
| view_count | number | View count is exposed as a title/tooltip attribute that often shows a rounded label like 'Viewed 12k times' in the visible text while the exact number hides in an attribute, so reading the rendered text loses precision and a selector targeting the human-readable span yields '12k' rather than 12000. |
| is_accepted_answer | boolean | There is no dedicated 'has accepted answer' field in the markup; you must infer it from the presence of a green check icon on one answer, and that icon is an SVG whose class and aria-label vary, so a class-based selector breaks while the boolean you actually want has to be derived rather than read directly. |
| asked_date | string | The ask date is shown as relative text ('asked 3 years ago') in the visible UI while the precise ISO timestamp sits in a title attribute on a nested time element, so scraping the displayed text gives you a fuzzy relative string instead of a parseable date and the attribute location shifts with layout changes. |
The schema-first approach
Instead of maintaining selectors, you hand Extracto a JSON schema describing the shape you want. Here is a schema that works for stackoverflow:
{
"title": "string",
"score": "number",
"answer_count": "number",
"tags": "array",
"view_count": "number",
"is_accepted_answer": "boolean",
"asked_date": "string"
} - 1
Describe the stackoverflow fields you want
Write a small JSON schema listing the fields to pull from stackoverflow.com (for example title, score, answer_count). No CSS selectors or XPath needed.
- 2
Send the URL and schema to Extracto
POST the stackoverflow page URL and your schema to the Extracto API. Extracto renders the page in a real browser, handling the HTML automatically.
- 3
Get schema-validated JSON back
Extracto returns JSON that matches your schema exactly, validated before it leaves the API, so your pipeline never receives broken or partial data.
Common pitfalls when scraping stackoverflow
- Score is upvotes minus downvotes and can be zero or negative on contentious or low-quality questions, so a schema that types it as a positive integer or treats 0 as missing will corrupt your dataset. Type it as a plain number and let Extracto return null only when the field is genuinely absent.
- Do not confuse the question's score and answer count with an answer's score: the same vote-count and check-mark markup repeats for every answer on the page, so a vague extraction can blend question-level and answer-level numbers. Anchor your schema field names to the question header semantics so the model targets the top post.
- View counts are displayed rounded ('Viewed 12k times') while the exact integer lives in an attribute; if you only capture the visible label you lose precision. Decide up front whether you want the human-readable string or the exact number, and validate the type accordingly.
- The accepted-answer state is not a literal field in the HTML; it is implied by a green check on one answer. Extracto can infer the boolean from page context, but for high-volume historical work the official Stack Exchange API or the CC BY-SA data dump expose this flag directly and avoid hammering the live site.
- Tags are sometimes localized or include synonyms, and the same tag chip markup appears in sidebars and related-question widgets, so a careless pass can over-collect. Scope your request to the question's own tag list to keep the array clean.
Is it legal to scrape stackoverflow?
Stack Overflow content is licensed under Creative Commons (CC BY-SA), and the network publishes periodic public data dumps plus an official Stack Exchange API, so the underlying question data is openly licensed and explicitly meant to be reused with attribution. That openness does not waive the site's Terms of Service: the Stack Exchange ToS and robots.txt still govern automated access to the live HTML, and aggressive crawling that ignores rate limits or load expectations can get an IP throttled or blocked. The license attaches to the question and answer text, not to user account details, so treat author profiles and any personal data with extra care under GDPR-style rules. For bulk historical analysis prefer the official API or the published data dump, which are the sanctioned, attribution-friendly paths. Reserve live scraping for the freshest, low-volume needs (a handful of specific question URLs), keep request volume modest, honor robots.txt, and preserve the CC BY-SA attribution and a link back to the source question wherever you republish extracted content. None of this is legal advice; confirm your specific use against the current Stack Exchange terms.
Extracto follows robots.txt by default and rate-limits politely. You are responsible for compliance with stackoverflow's terms and applicable law (GDPR, CCPA) in your use case.