Twitter X Tweets Scraper Scraper With Poll Results
Pricing
from $3.99 / 1,000 results
Twitter X Tweets Scraper Scraper With Poll Results
Scrape public tweets from X Twitter with precision. Extract tweet text, timestamps, likes, retweets, replies, hashtags, mentions, and author data. Filter by keywords, profiles, or time range. Ideal for research, monitoring trends, lead generation, and content analysis.
Pricing
from $3.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapio
Maintained by CommunityActor stats
0
Bookmarked
8
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
Twitter X Poll Scraper β Extract Posts, Polls and Author Profiles
Twitter X Poll Scraper reads public X (Twitter) profile timelines and single post URLs and returns typed JSON for every post, including the poll card riding on it: each option in X's own order, the vote count X published for it, whether the count is still moving, and the posting author's profile stats. Unlike scraping frameworks that return raw HTML or a truncated poll question, this actor returns the actual choices and counts as structured fields β ready for a spreadsheet, a database, or an LLM context window with no parsing step. No X login is required for anything poll-related; a session is needed only to also read a profile's replies. This guide covers every input and output field and how teams run it for live monitoring, one-off lookups, and bulk dataset builds.
π§ What Does Twitter X Poll Scraper Do?
Twitter X Poll Scraper is an Apify Actor that fetches X (Twitter) profile timelines or single post URLs through X's own GraphQL API and turns each post into one dataset row. Every row carries the full post record (text, engagement counts, media, hashtags, mentions, quoted post) and the author's profile stats, plus β the reason this variant exists β the poll card: options, per-option vote counts, whether voting has closed, and image-poll artwork. No X account is required for polls, timelines, or single post URLs; an X session (auth_token + ct0 cookies) is required only for the option to also read a profile's own replies.
- π³οΈ Extracts poll options in X's own 1β4 order, with the vote count published for each
- β³ Derives
poll_status(open/closed) from X's owncounts_are_finalflag, never from a clock - πΌοΈ Reads image-poll option artwork, which most poll parsers drop
- π Optionally expands non-poll link-preview cards into their own
link_cardfields - π Returns the full post record β text, likes, replies, reposts, quotes, bookmarks, views, media, hashtags, mentions, quoted post
- π€ Returns the author's profile stats on every row β followers, following, post count, bio, verification
- π Resolves a repost to the original post's real card, counts and author, never the retweet wrapper's structural zeros
β‘ Features & Capabilities
Twitter X Poll Scraper's core job is reading the poll card that most X scrapers ignore, on top of a complete post and author record.
Core features
- Poll options and vote counts read straight from X's response β no extra request, no browser
poll.options[]withposition(X's own 1β4 index),label,votes, andimage_urlfor picture pollspoll.option_count,poll.total_votes(computed sum of published option counts),poll.counts_are_final,poll.duration_minutes,poll.end_datetime_utc,poll.last_updated_datetime_utcis_pollsettrueeven when a poll card fails to parse β a run log line names the raw binding keys instead of silently reporting "no poll"- Two local filters β
onlyPollPostsandpollStatusβ that drop non-matching posts before anything is charged - Optional
link_cardblock for non-poll cards: title, description, domain, destination URL, thumbnail, and the embedded player URL on video cards - Full post fields:
description(post text, preferring the untruncated long-form version),likes,replies,reposts,quotes,bookmarks,views,hashtags,tagged_users,photos,videos,media,quoted_post - Full author fields on every row:
user_posted,name,followers,following,posts_count,biography,external_url,is_blue_verified,verified_type,profile_image_link
When this actor is not the right fit
If a target account never posts polls, no scraper can invent one β X's own filter:polls search operator returns zero results, so there is no way to search X for "every poll about a topic," only to read the polls a specific account or post already carries. If the goal is following, follower-list, or audience-graph data rather than posts and polls, that is a structurally different output shape covered by a sibling actor (see Related Scrapers below), not this one.
Twitter X Poll Scraper within the Scrapio data stack
Twitter X Poll Scraper covers posts, polls and author stats. For follower and following rosters as their own dataset rows, use X (Twitter) Profile, Posts and Follower List Scraper. Both read the same public GraphQL surface and need no X session except for their respective auth-gated options.
πΌ Why do developers and data teams scrape X (Twitter)?
X remains one of the few large platforms where an account states public opinion as a structured number β a poll β rather than free text, which is why teams build pipelines around it rather than reading it by hand.
π’ Marketing and brand research
Brands running or watching a poll about a product, campaign, or announcement pull poll.options[], poll.choices[].votes, and poll_status into a report the moment a poll closes, instead of manually refreshing the post and copying numbers by eye. followers and is_blue_verified on the author row help judge how much weight to give the result.
π AI training data and RAG indexing
description (the post text β the poll question, in the case of a poll post) is the highest-information text field for RAG indexing: it is the actual claim being voted on. For training data, poll.options[].label and poll.options[].votes give a consistent, typed structure across every poll post, and likes / replies / reposts / views are numeric engagement features with no normalization needed. Two uses: (1) RAG enrichment β feed description plus the poll options into a retrieval index so an agent can answer "what did X users think about Y"; (2) training data β the typed poll.choices[] array is a clean label/count pair per example, with no HTML to strip.
π± Competitive and market intelligence
Track a competitor's or an industry account's poll cadence and results over time by re-running against the same startUrls and diffing poll.choices[].votes and poll_status between runs β a poll flipping from open to closed is the signal that the number is now final and quotable.
π¬ Research and academic use
Social and market researchers building datasets of self-reported public opinion can collect poll.options[], poll.total_votes, and the author's follower count as context, from public accounts only β this actor never touches a protected timelineβs posts.
π₯ Product and SaaS development
Building a poll-monitoring dashboard, a brand-sentiment tool, or a social-listening feature on top of typed poll data, without maintaining an X GraphQL client, bearer-token discovery, or a card parser in-house.
π Input Parameters
All parameters below come directly from the Actor's input schema (.actor/actor.json), in schema order.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
startUrls | Yes | array of strings | One target per line: a profile URL (https://x.com/NASA or https://twitter.com/NASA), a handle (NASA or @NASA), a numeric user ID (e.g. 11348282), or a single post URL (https://x.com/farzyness/status/1887685445791740273). A post URL returns exactly one row and ignores the post limit. | ["https://x.com/farzyness/status/1887685445791740273"] |
maxTweets | No | integer (min 1, max 1000, default 10) | How many posts to READ per profile β the request budget, not a poll quota. The poll filters run afterwards on posts already fetched, so a low value on an account that polls rarely will usually keep nothing. The pinned post counts toward this limit; duplicates are removed before charging. Not applied to single post URLs. | 100 |
onlyPollPosts | No | boolean (default false) | Off: every post is returned, poll or not. On: posts without a poll are dropped before anything is charged. | true |
pollStatus | No | string, enum any / open / closed (default any) | Filter by whether voting is still running, from X's own counts_are_final flag. any keeps both. Choosing open or closed can only match posts that carry a poll β ordinary posts are dropped too. | "closed" |
includeLinkPreviewCards | No | boolean (default false) | Off by default. On: fills the link_card field for posts whose card is a non-poll link preview (card type, title, description, domain, destination URL, thumbnail, embedded player URL). Reads the same response β adds no extra request. | false |
sortOrder | No | string, enum recent / oldest / popular (default recent) | Re-orders the rows collected in this run, after filtering. X always serves a timeline newest-first; this does not search further back than the posts already fetched. | "recent" |
includeReplies | No | boolean (default false) | Off: the profile's posts, reposts and quotes (the "Posts" tab) β no login needed. On: also the replies that profile wrote to other people (the "Posts and replies" tab) β requires auth_token + ct0; the run fails immediately if they are missing rather than returning a partial timeline. | false |
auth_token | No | string (secret) | Optional. Needed only for includeReplies. The auth_token cookie value from an x.com browser session. Stored encrypted, sent only to api.x.com, never written to the dataset or run log. | (empty) |
ct0 | No | string (secret) | Optional, required together with auth_token. The ct0 (CSRF) cookie value from the same x.com browser session. Stored encrypted, sent only to api.x.com, never written to the dataset or run log. | (empty) |
proxyConfiguration | No | object (default {"useApifyProxy": false}) | Off by default β X was measured serving poll cards to a bare Apify datacenter exit. Turn on Apify Proxy for a different exit or high-volume runs; the actor rotates to a fresh exit once if a request fails before any row was saved. | {"useApifyProxy": false} |
JSON input example
{"startUrls": ["https://x.com/farzyness/status/1887685445791740273", "NASA"],"maxTweets": 50,"onlyPollPosts": true,"pollStatus": "closed","includeLinkPreviewCards": false,"sortOrder": "recent","includeReplies": false,"proxyConfiguration": { "useApifyProxy": false }}
Supported URL types and input formats
startUrls accepts, per target line:
- A profile URL β
https://x.com/NASAorhttps://twitter.com/NASAβ reads that profile's timeline - A bare handle β
NASAor@NASAβ resolved the same way as the profile URL - A numeric user ID β
11348282β for accounts referenced by ID rather than handle - A single post URL β
https://x.com/farzyness/status/1887685445791740273β returns exactly one row for that post and ignoresmaxTweets; this is the fastest path to a specific poll, since polls are rare on most timelines
Mixed input, one profile and one direct poll link:
{ "startUrls": ["NASA", "https://x.com/farzyness/status/1887685445791740273"] }
π¦ Output Format
Every run produces typed, normalized JSON β one row per post β with a consistent schema across runs. Export from the Apify Console or via apify_client as JSON, CSV, Excel (XLSX), or XML.
Output for posts
Every key the Actor writes to a post row, copied from src/base_row.py and src/poll_row.py:
{"type": "tweet","id": "1887685445791740273","url": "https://x.com/farzyness/status/1887685445791740273","user_posted": "farzyness","name": "Farzad","description": "Who do you trust more in government - the current class of politicians, or a 19 year old DOGE engineer?","date_posted": "2025-02-07T02:10:56.000Z","likes": 11545,"replies": 1335,"reposts": 4116,"quotes": 263,"bookmarks": 378,"views": 25902230,"lang": "en","conversation_id": "1887685445791740273","is_repost": false,"reposted_by": null,"is_quote": false,"is_reply": false,"in_reply_to_user": null,"in_reply_to_post_id": null,"is_pinned": false,"is_verified": true,"is_blue_verified": true,"verified_type": null,"followers": 182340,"following": 512,"posts_count": 48210,"profile_image_link": "https://pbs.twimg.com/profile_images/example_400x400.jpg","biography": "Building things.","external_url": "https://example.com","hashtags": null,"tagged_users": null,"photos": null,"videos": null,"media": null,"quoted_post": null,"poll": {"card_type": "poll4choice_text_only","choices": [{ "label": "Politicians", "votes": 5060 },{ "label": "19 y/o DOGE Engineer", "votes": 181847 },{ "label": "Not sure", "votes": 4578 },{ "label": "See results", "votes": 26823 }],"total_votes": 218308,"counts_are_final": true,"duration_minutes": 1440,"end_datetime_utc": "2025-02-08T02:10:56Z","last_updated_datetime_utc": "2025-02-08T02:11:00Z","option_count": 4,"options": [{ "position": 1, "label": "Politicians", "votes": 5060, "image_url": null },{ "position": 2, "label": "19 y/o DOGE Engineer", "votes": 181847, "image_url": null },{ "position": 3, "label": "Not sure", "votes": 4578, "image_url": null },{ "position": 4, "label": "See results", "votes": 26823, "image_url": null }],"is_image_poll": false},"link_preview": null,"input": { "url": "https://x.com/farzyness/status/1887685445791740273" },"is_poll": true,"poll_status": "closed","link_card": null}
An unavailable count is written as null, never 0; an unavailable string is null, never "" β a field the actor did not measure is never faked as a zero or an empty string.
Output for polls
The poll object (and the added is_poll / poll_status keys) on a post that carries a poll:
{"is_poll": true,"poll_status": "open","poll": {"card_type": "<id>:poll_choice_images","choices": [{ "label": "Yes", "votes": null },{ "label": "No", "votes": null }],"total_votes": null,"counts_are_final": false,"duration_minutes": 1440,"end_datetime_utc": "2026-08-10T18:00:00Z","last_updated_datetime_utc": null,"option_count": 2,"options": [{ "position": 1, "label": "Yes", "votes": null, "image_url": "https://pbs.twimg.com/card_img/example_yes.jpg" },{ "position": 2, "label": "No", "votes": null, "image_url": "https://pbs.twimg.com/card_img/example_no.jpg" }],"is_image_poll": true}}
This example is an image poll, measured (2026-08-03) to sometimes publish no choiceN_count at all β votes and total_votes are null, never a fabricated 0, and option_count comes from X's own choice_count binding rather than from counting _count keys (which would over-count on an image poll).
Output for author profiles
Author fields are returned flat on every post row (not as a separate nested object), read from the post's author block:
{"user_posted": "farzyness","name": "Farzad","biography": "Building things.","external_url": "https://example.com","followers": 182340,"following": 512,"posts_count": 48210,"profile_image_link": "https://pbs.twimg.com/profile_images/example_400x400.jpg","is_verified": true,"is_blue_verified": true,"verified_type": null}
On a repost, these fields describe the original post's author, not the reposting account β the reposting account's handle is in reposted_by instead.
Schema stability and export options
Field names are fixed by this actor's own row-building code, not by X's raw GraphQL response shape β a front-end change on X.com does not rename a dataset column, since the response is parsed and re-keyed before anything is pushed. A field X stops sending shows up as null, not as a missing key, so downstream code that reads a fixed column list keeps working. Export any run's dataset from the Apify Console, or programmatically via apify_client, as JSON, CSV, Excel (XLSX), or XML; the dataset also exposes five extra pre-built views (Poll results, Link cards, Media & entities, Reposts/quotes/pinned, Author profile) alongside the default Posts view for quicker inspection in the Console.
π‘ Twitter X Poll Scraper Strategy Guide
π― Strategy 1: Real-time poll-result enrichment
Trigger a run β manually, via a webhook, or from a scheduled task β with the poll's own post URL in startUrls. Read poll.options[], poll.total_votes, and poll_status from the single returned row and append them to a CRM record, a campaign-tracking sheet, or a report, without waiting for a scheduled crawl. Because a post URL ignores maxTweets, this is the cheapest and fastest way to get one specific poll's numbers.
π― Strategy 2: Scheduled monitoring of an open poll
Use an Apify Schedule to re-run the same startUrls at a fixed interval while poll_status is open. Diff poll.choices[].votes and poll.last_updated_datetime_utc against the previous run's dataset to see how the numbers are moving, and alert when a later run reports poll_status: "closed" β that transition is the signal the count is now final and quotable, straight from X's own counts_are_final flag.
π― Strategy 3: Bulk poll-dataset build across many accounts
Feed a list of profile handles into startUrls with onlyPollPosts: true and a high maxTweets, since polls are rare per account. Run the actor once per batch of targets, or split targets across parallel runs started via the Apify API, then aggregate every run's dataset into one CSV or database table for a social-listening or market-research dataset. Apify does not publish a fixed concurrency limit for parallel Actor runs β how many run at once depends on your own Apify plan and account limits, not a number this actor sets.
Strategy comparison at a glance
| Strategy | Best for | Run pattern | Output format |
|---|---|---|---|
| Real-time enrichment | One known poll, needed now | Single post URL, on-demand run | One JSON row, read immediately |
| Scheduled monitoring | Watching a poll while it's open | Same target, re-run on an Apify Schedule | Dataset rows compared run-over-run |
| Bulk dataset build | Many accounts, research or BI | Batched or parallel runs over a target list | Aggregated CSV / database table |
π΄ Related X Scrapers & Tools
| Scraper | What it extracts |
|---|---|
| X (Twitter) Profile, Posts and Follower List Scraper | X profile, recent posts, and β with your own session cookies β the actual follower and following rosters as their own rows |
| Threads Search Post Scraper With Engagement Analytics | Posts and engagement metrics from Threads, for teams tracking the same audience on Meta's microblogging platform |
| Reddit Subreddit Members Scraper With User Profiles | Active participants in a subreddit plus their profile stats β a complementary public-opinion signal alongside X polls |
π How to integrate Twitter X Poll Scraper with your stack
Twitter X Poll Scraper works with any language or tool that can make an HTTP request, since every run is a standard Apify Actor run reachable through the Apify API or an official Apify client library.
Python
from apify_client import ApifyClientimport csvclient = ApifyClient("<APIFY_API_TOKEN>")run_input = {"startUrls": ["NASA", "https://x.com/farzyness/status/1887685445791740273"],"maxTweets": 100,"onlyPollPosts": True,"pollStatus": "any",}run = client.actor("<YOUR_APIFY_USERNAME>/twitter-x-tweets-scraper-scraper-with-poll-results").call(run_input=run_input)with open("poll_results.csv", "w", newline="", encoding="utf-8") as f:writer = csv.writer(f)writer.writerow(["id", "user_posted", "description", "poll_status", "total_votes"])for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item.get("type") != "tweet":continue # skip uncharged accounting rowspoll = item.get("poll") or {}writer.writerow([item.get("id"),item.get("user_posted"),item.get("description"),item.get("poll_status"),poll.get("total_votes"),])
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_API_TOKEN });const input = {startUrls: ['NASA', 'https://x.com/farzyness/status/1887685445791740273'],maxTweets: 100,onlyPollPosts: true,pollStatus: 'any',};const run = await client.actor('<YOUR_APIFY_USERNAME>/twitter-x-tweets-scraper-scraper-with-poll-results').call(input);const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const row of items) {if (row.type !== 'tweet') continue; // skip uncharged accounting rowsconsole.log(row.user_posted, row.poll_status, row.poll?.total_votes);}
Async and scheduled pipelines
There is no webhook fired from inside the Actor's own code, but the Apify platform can call one for you β configure a webhook on the run-finished event from the Console or API to get notified once a run completes. For a recurring poll-monitoring job, use an Apify Schedule (cron) to re-run the Actor on a fixed interval instead of polling. For a large one-off batch, start the run with apify_client and either .call() (blocks until finished) or poll client.run(run_id).get() for its status.
π― Who Needs Twitter X Poll Scraper? (Use Cases & Industries)
π’ Marketing and brand teams
Pull the final options and vote counts of a branded or campaign poll into a report the moment poll_status flips to closed, without manually screenshotting the post.
π AI and data engineering teams
Feed description and poll.options[] into a RAG index for "what did the public say about X" queries, or use the typed poll.choices[] array as a clean label/count training example β no HTML to strip, no missing fields silently coerced to zero.
π± Market and competitive intelligence analysts
Track a competitor's or industry account's poll results and cadence over time, diffing poll.choices[].votes and poll_status between scheduled runs.
π¬ Researchers
Build a dataset of public, self-reported opinion from X polls β poll.options[], poll.total_votes, and author follower counts as context β from public accounts only.
π₯ Product and SaaS builders
Ship a poll-monitoring dashboard, sentiment tracker, or social-listening feature on typed poll data without building and maintaining an X GraphQL client or card parser in-house.
βοΈ Is it legal to scrape X (Twitter)?
Scraping publicly accessible posts and poll results from X (Twitter) is generally lawful in the United States β courts have distinguished accessing public web data from unauthorized computer access. In hiQ Labs, Inc. v. LinkedIn Corp., 938 F.3d 985 (9th Cir. 2019), the Ninth Circuit held that scraping data a website makes publicly available does not violate the Computer Fraud and Abuse Act. That case concerned public profile data on LinkedIn, not X specifically, but the underlying reasoning β that "public" means public β is widely cited for public-data scraping generally.
Separately, X's own Terms of Service restrict automated access and scraping. Violating a platform's Terms of Service is a potential civil contract dispute between the account holder and the platform, not a criminal matter.
Because posts and their author fields (user_posted, name, biography, followers, profile_image_link) identify real, often individual, account holders, this data can be personal data under GDPR and the CCPA once you store or reuse it. Lawful basis for that storage and reuse sits with you as the operator, not with this actor.
Twitter X Poll Scraper returns only publicly accessible data. What you do with that data is your responsibility β consult legal counsel for commercial applications involving personal data.
β Frequently asked questions
Does Twitter X Poll Scraper work without an X (Twitter) account?
Yes, for everything poll-related. Poll options, vote counts, poll status, image-poll artwork, profile timelines, and single post URLs were all measured working through a keyless guest token. An X session (auth_token + ct0) is required only for the includeReplies option, which reads the "Posts and replies" tab X serves only to logged-in callers.
How does Twitter X Poll Scraper handle X's anti-scraping measures?
It discovers the current public web bearer token and GraphQL operation IDs at runtime by parsing X's own web client bundle (cached for 6 hours), rather than hardcoding values that go stale when X redeploys. Requests go through a Chrome-impersonating HTTP client. On an HTTP 429, it rotates to a fresh guest token (keyless rate-limit buckets are per token) and, if the reset window is short, waits it out before retrying once. If a request fails before any row is saved and Apify Proxy is enabled, it rotates to a fresh proxy exit and retries once.
Can I run Twitter X Poll Scraper at scale without getting blocked?
maxTweets is capped at 1000 posts read per target, and X's own rate-limit headers (x-rate-limit-limit, x-rate-limit-remaining, x-rate-limit-reset) are read and logged per run rather than guessed at. No uptime or success-rate figure is published for this actor.
How fresh is the data Twitter X Poll Scraper returns?
Every run fetches live from X at request time; post and poll data is not cached. (The only thing cached is the discovered bearer token and GraphQL operation IDs, for up to 6 hours, since those rarely change β never the posts or vote counts themselves.) A poll's vote counts are a snapshot at the moment your run read them; re-run to see how they've moved.
Is it legal to scrape public X posts and polls?
Generally yes for the public-data-access question β see hiQ Labs, Inc. v. LinkedIn Corp., 938 F.3d 985 (9th Cir. 2019). The separate questions of X's Terms of Service and data protection law for the personal data embedded in author fields are covered above.
Which fields work best for AI training and RAG indexing?
For RAG: description (the post text, including the poll question) is the highest-information text field. For training data: poll.options[].label and poll.options[].votes form a consistent label/count structure across every poll post, and likes, replies, reposts, views are numeric engagement features. All fields return as typed primitives β strings, integers, booleans, or null β with no HTML to strip and no normalization required before use.
Does Twitter X Poll Scraper collect personal data, and who is responsible for it?
Yes β author fields like user_posted, name, biography, and followers identify real account holders and can be personal data under GDPR/CCPA. The actor returns only what X already publishes publicly; the lawful basis for storing, processing, or reusing that data is the operator's responsibility, not the actor's.
Does Twitter X Poll Scraper work with Claude, ChatGPT, and other AI agent tools?
It is not exposed through an MCP server. It is callable as a standard Apify Actor run by any agent framework that can call the Apify API or use apify_client β every response is typed JSON, so an agent can read poll.options[] or description directly without an HTML-parsing step.
What happens to the poll when the post is a repost?
The row is built from the original post, not the retweet wrapper, so a reposted poll keeps the original's card, vote counts, and author fields, with the reposting account named separately in reposted_by.
βΉοΈ Disclaimer
Twitter X Poll Scraper extracts only publicly available data from X (Twitter). This tool is intended for lawful use cases only. Users are responsible for complying with X's terms of service and applicable data protection laws in their jurisdiction.