Twitter User Tweets Scraper | X Profile Scraper avatar

Twitter User Tweets Scraper | X Profile Scraper

Pricing

from $1.20 / 1,000 tweet results

Go to Apify Store
Twitter User Tweets Scraper | X Profile Scraper

Twitter User Tweets Scraper | X Profile Scraper

Scrape public X/Twitter user timelines with Tweets, author data, engagement, replies, quotes, reposts, media, date filters, and batch processing.

Pricing

from $1.20 / 1,000 tweet results

Rating

0.0

(0)

Developer

LanceAPI

LanceAPI

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

13 hours ago

Last modified

Categories

Share

X / Twitter User Tweets Scraper

Turn public X/Twitter profiles into rich, ready-to-use Tweet datasets.

Enter usernames or profile links to collect timeline posts with text, author profiles, engagement, media, replies, quotes, and repost context. Export JSON or CSV, or feed the results into your own research and automation workflows.

  • Rich context: quoted and reposted Tweets stay attached to the parent result, including available author and media details.
  • Clean datasets: one row represents one real Tweet. Duplicate Tweet IDs are saved once per run.
  • Batch profiles: submit up to 200 profile entries, with per-profile and run-wide result controls.
  • Tweet result charge protection: pay the Tweet result fee only for unique Tweets saved as Dataset rows. Quoted and reposted context stays nested instead of creating extra Tweet result charges. Platform usage charges are separate.
  • Focused collections: choose a date range and whether to include replies and reposts.
  • Honest missing values: unavailable metrics remain null, not invented zeroes.

Quick start

  1. Enter a public username or profile URL in Profiles.
  2. Keep Results per profile at 15 for a first run, then click Start.
  3. Open Tweet results to view or export the Dataset. Open Run summary for empty profiles, errors, and collection statistics.
{
"profiles": ["https://x.com/elonmusk"],
"maxResultsPerProfile": 15
}

No X login or cookies are required. Private accounts are not supported.

Input reference

FieldTypeRequiredDefault / prefillMeaning
profilesstring arrayYesUI prefill: https://x.com/elonmusk; no runtime default1–200 usernames, @usernames, or X/Twitter profile URLs.
maxResultsPerProfileintegerNo15Maximum final unique Tweets per profile, after filtering: 1–500 for all plans. Free allowance, availability, filters and scan limits may reduce the result count.
maxItemsintegerNoUnsetPositive run-wide unique Tweet limit. Stops remaining collection once reached.
dateRangestringNolatestlatest, last_24_hours, last_7_days, last_30_days, or since_date. Date-filtered collections always end at run time.
startDatestringNoUnsetOptional starting date. When filled, overrides dateRange and collects from this date until run time. Clear it to use a recent preset.
timezonestringNoUTCIANA time zone for calendar dates and relative months/years, for example Asia/Shanghai.
includeRepliesbooleanNotrueInclude reply Tweets. Turn off to exclude replies.
includeRetweetsbooleanNotrueInclude reposts. Quoted Tweets remain eligible.

Accepted profile forms include elonmusk, @elonmusk, https://x.com/elonmusk, and https://twitter.com/elonmusk. Equivalent profiles are processed once, case-insensitively. Numeric-looking usernames are treated as usernames, not account IDs. Tweet links and search queries are not inputs for this Actor.

Choose a Time range directly in the form: latest Tweets by result count, last 24 hours, last 7 days, last 30 days, or From a date until now. Alternatively, fill From date and it automatically takes precedence over the dropdown, including its default selection. Clear that date to return to a recent preset. There is no separate end date or Absolute/Relative pair to configure.

Select Time zone from the labelled choices, such as China — Beijing / Shanghai, or enter another valid IANA zone. The default is UTC. For since_date, a YYYY-MM-DD starts at local midnight and ends at run time. Explicit ISO timestamps with Z or an offset still represent the same instant; output createdAt remains UTC. Future starting dates are rejected.

Recent presets are rolling 24-hour, 7-day, or 30-day windows, calculated from one stable run reference time. The Actor scans a limited recent timeline window and may return fewer Tweets than requested. It does not search an arbitrary historical date interval or guarantee every Tweet since an old starting date. endDate is no longer supported: old API requests that include it fail input validation before collection. Any non-empty startDate selects since_date, even if dateRange contains a preset; an empty or null date uses the preset. Tweets without usable creation times cannot match a date filter.

{
"profiles": ["elonmusk", "aviationbrk"],
"maxResultsPerProfile": 100,
"maxItems": 150,
"dateRange": "last_7_days",
"includeReplies": false,
"includeRetweets": false
}

Result limits apply to final unique Tweet rows, not unfiltered candidates. Restrictive filters can require more collection work and still yield fewer results. maxItems is a result-volume guardrail, not a cap on all platform charges.

Output

Each Dataset row is a real top-level timeline Tweet. Tweets are sorted newest-first within each processed profile. Profiles are processed in input order; the entire Dataset is not globally sorted across profiles.

Quotes and reposts preserve full nested Tweet context up to two levels deep. Nested context does not create extra rows or separate result charges. Separately attached pinned posts are excluded. A pinned post that also appears naturally in the ordinary timeline remains eligible.

Short example

The following is a reduced excerpt from a captured public Tweet response. Metrics are a snapshot, not current values.

{
"tweetId": "2112039275344941371",
"url": "https://x.com/thsottiaux/status/2112039275344941371",
"text": "I bought a new domain and I’m very excited for it. Very",
"createdAt": "2026-10-19T04:32:57.000Z",
"authorUsername": "thsottiaux",
"type": "tweet",
"likesCount": 5477,
"viewsCount": 821206,
"bookmarksCount": 179
}

Complete Tweet example

This full canonical example was normalized from a captured public response. The parent repost contains a structured mention and the original post's photo. Snapshot metrics and media availability can change.

Field reference

FieldsType / meaning
tweetIdExact string identity, suitable for database joins and deduplication.
url, text, createdAt, language, conversationIdPublic source link, fullest available text, UTC ISO timestamp, language code, and conversation identity; unavailable values are null.
typetweet, reply, retweet, or quote. Primary classification prioritizes retweet, then reply, then quote.
isReply, isRetweet, isQuoteIndependent factual relationship booleans; more than one may be true.
source, possiblySensitiveAvailable posting-client label and sensitivity flag. Missing values are null.
authorId, authorUsername, authorNameConvenient author identity fields.
likesCount, repliesCount, retweetsCount, quotesCount, bookmarksCount, viewsCountNumeric counts or null; an explicit zero stays zero.
engagementThe same counts under likes, replies, retweets, quotes, bookmarks, and views.
authorSee author fields below.
replyToTarget tweetId, userId, and username, with unavailable parts null; null for non-replies.
quotedTweet, retweetedTweetFull canonical nested Tweets or null. Relationships deeper than two levels are null.
mediaArray of media records; see below.
hashtags, cashtagsString arrays.
mentionsArray of {userId, username, name} objects; unavailable parts are null.
urlsArray of {url, expandedUrl, displayUrl} objects; unavailable parts are null.
cardAvailable name, url, title, description, and imageUrl, or null.
inputProfile, profileUsernameThe original input reference and normalized collection username, so multi-profile results remain attributable.
scrapedAtUTC ISO collection timestamp.

Author fields: id, username, name, description, verified, blueVerified, verifiedType, followersCount, followingCount, tweetCount, mediaCount, favouritesCount, listedCount, profileImageUrl, profileBannerUrl, location, website, createdAt, protected, and professionalType. Unavailable fields are null. Traditional verification and blue verification are separate signals; one does not imply the other.

Media fields: id, mediaKey, type (photo, video, or animated_gif), url, thumbnailUrl, expandedUrl, width, height, aspectRatio (a two-number array), durationSeconds, hlsUrl, variants, allowDownload, and altText. Each variant has url, contentType, and nullable bitrate. For video, url prefers the highest-bitrate available MP4, otherwise HLS. Dimensions are pixels, duration is seconds, and bitrate is bits per second. Availability varies by Tweet.

The default table emphasizes text, author, type, creation time, engagement, source link, and profile attribution. Open a row or export JSON for nested details; CSV exports may encode nested objects as JSON.

Run summary and errors

Empty or unavailable profiles do not create placeholder Dataset rows. One unavailable profile does not stop the rest of the batch. Successfully collected Tweets are retained if a later collection step fails.

The Run summary contains requestedProfiles, uniqueProfiles, successfulProfiles, emptyProfiles, failedProfiles, skippedProfiles, tweetsDelivered, duplicatesRemoved, filteredOut, and profiles. Each profile includes its status, delivered count, pages fetched, and stop reason. requestedProfiles counts submitted entries; equivalent profiles are processed once. A partially successful profile counts as successful and retains an explicit partial_success status.

Common stop reasons include limit_reached, global_limit_reached, timeline_exhausted, no_new_unique_tweets, repeated_cursor, scan_budget_reached, page_safety_limit, not_found, private_profile, suspended, and upstream_error. scan_budget_reached means the recent scanning window ended; saved results are retained and a full historical archive is not implied.

Error codeWhat to do
INVALID_INPUTCheck the profile format and input types.
PROFILE_NOT_FOUNDVerify the username still exists.
PRIVATE_PROFILE, PROFILE_SUSPENDEDTry another publicly accessible account.
TWEETS_UNAVAILABLETemporary access or data-format issue; try again later.
FREE_USAGE_LIMIT_EXCEEDEDYour free allowance has been reached.
FREE_USAGE_CHECK_FAILEDThe allowance could not be verified; retry later.

Malformed run-wide configuration, such as an invalid date range, fails input validation before collection.

Pricing

The result-billing unit is one unique Tweet successfully saved to the Dataset. Duplicate, filtered, nested, separately attached pinned, failed, private, and empty results do not create a Tweet result charge.

Formal dollar pricing is pending the product owner's rates and configuration. Check the Actor's Pricing tab for the current terms before running it; no dollar rate is promised here. Platform usage charges may apply independently. Use maxResultsPerProfile and maxItems to control result volume.

Practical uses

  • Creator research: compare public posting patterns and engagement in your own analysis tools.
  • Brand monitoring: collect posts from a known list of public accounts for review.
  • News tracking: keep source-linked timeline records from public news profiles.
  • Media research: inspect available photos, video variants, and quoted-post context.
  • Dataset building: join exact Tweet and author IDs with your own records.
  • AI workflows: feed text and relationship context into your own summarization, clustering, or retrieval pipeline. The Actor does not perform those analyses itself.

API integration

Set APIFY_TOKEN in your own environment. Do not put tokens in URLs or public code.

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('lance_api/x-twitter-user-tweets-scraper').call({
profiles: ['elonmusk'],
maxResultsPerProfile: 15,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('lance_api/x-twitter-user-tweets-scraper').call(run_input={
'profiles': ['elonmusk'],
'maxResultsPerProfile': 15,
})
for tweet in client.dataset(run['defaultDatasetId']).iterate_items():
print(tweet['tweetId'], tweet['text'])

REST / cURL

Requires cURL and jq. Start a run, wait for completion, then fetch its Dataset:

set -eu
: "${APIFY_TOKEN:?Set APIFY_TOKEN first}"
run=$(curl --fail --silent --show-error \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"profiles":["elonmusk"],"maxResultsPerProfile":15}' \
'https://api.apify.com/v2/acts/lance_api~x-twitter-user-tweets-scraper/runs')
run_id=$(echo "$run" | jq -er '.data.id')
while :; do
run=$(curl --fail --silent --show-error \
-H "Authorization: Bearer $APIFY_TOKEN" \
"https://api.apify.com/v2/actor-runs/$run_id?waitForFinish=60")
status=$(echo "$run" | jq -er '.data.status')
case "$status" in
SUCCEEDED) break ;;
READY|RUNNING|TIMING-OUT|ABORTING) ;;
*) echo "Run ended with status: $status" >&2; exit 1 ;;
esac
done
dataset_id=$(echo "$run" | jq -er '.data.defaultDatasetId')
curl --fail --silent --show-error \
-H "Authorization: Bearer $APIFY_TOKEN" \
"https://api.apify.com/v2/datasets/$dataset_id/items?format=json&clean=true"

Schedule runs in Apify or integrate the Actor into your own application and automation tools. Deduplication applies within a run, not across separate runs.

For Tweet details and keyword search, use the X (Twitter) Tweet Scraper. Explore more tools on the lance_api profile.

FAQ

Can I retrieve a complete account history? No fixed historical depth is guaranteed. The requested count is a maximum, not a promise; X may expose only part of the history.

Do I need to log into X? No X login or cookies are required for the supported public collection workflow.

Why are some values null? Certain posts do not expose every metric or metadata field. A missing value is kept distinct from an actual zero or false.

Are quoted and reposted Tweets billed twice? No. Nested context stays in the parent row and does not create a separate result charge.

Does a failed collection use my free Tweet allowance? Where a Tweet allowance applies, only successfully saved unique Tweet results count. An attempt with no saved result does not consume that allowance. Platform usage charges are separate.

Can I collect several profiles? Yes, up to 200 submitted profile entries. Use a run-wide limit when you do not want the full per-profile maximum from every profile.

What happens if I submit the same profile twice? Equivalent usernames, @usernames, and profile URLs are canonicalized and deduplicated case-insensitively. The profile is processed once in this run.

Can I exclude replies or reposts? Yes, with the two include flags. Quotes are not independently switchable; ordinary date and reply/repost filters still apply.

Limitations and responsible use

Only publicly accessible data can be returned. Protected, suspended, deleted, or restricted accounts may return no Tweets. Historical depth and optional metadata can vary, and media links can expire. Filtering may reduce results below the requested maximum. The Actor does not guarantee a complete archive or a fixed count.

Collect only data you are permitted to access and use. Respect privacy, copyright, applicable law, and platform terms. Do not use the results for spam or harassment.

Support

Open an issue on the Actor page or email lanceapi2026@hotmail.com. Include the Run ID, non-sensitive input, expected result, and actual summary/error code. Never send tokens, passwords, cookies, API keys, session credentials, proxy credentials, or authorization headers.