Twitter Media Scraper
Pricing
$0.10 / 1,000 media links
Twitter Media Scraper
Get public Twitter/X images, videos, and GIFs from tweet URLs, IDs, profiles, hashtags, or keywords. Export direct media links with post, author, profile, and engagement data.
Pricing
$0.10 / 1,000 media links
Rating
0.0
(0)
Developer
Maxime Dupré
Maintained by CommunityActor stats
0
Bookmarked
78
Total users
12
Monthly active users
7 hours ago
Last modified
Categories
Share
📥 Get public Twitter/X media links
Twitter Media Scraper helps researchers, marketers, and developers find public images, videos, and GIFs. Give it tweet URLs, IDs, profiles, hashtags, or keywords. It returns direct source-hosted media links with post, author, profile, and engagement data.
- Use Twitter Scraper Media Research to collect public media and post data for research.
- Use X Scraper to discover public media from hashtags and keyword searches.
- Use Twitter Scraper Apify to run a public media search in an Apify workflow.
- Use Twitter Scraper Without API to collect public media without an X or Twitter login.
- Run Twitter Image Scraper to get direct image links with author data.
- Run Twitter Video Scraper to get direct video links with post context.
- Build Twitter Media Archive from known public tweet URLs or IDs.
- Use Twitter Media API Workflows to pass direct links and post data to later steps.
📊 Twitter/X media rows
Each dataset row is one image, video, or GIF. When the same source media appears through more than one target, the Actor saves the first eligible match and ignores later matches. The row shows the first target that found it. Data can include:
- A direct media URL, thumbnail, media type, size, alt text, and source order
- The source post URL, text, date, language, and public engagement counts
- The author's username, name, profile URL, avatar, and verification status
- Profile facts when media comes from a profile target
- The direct media link and other video quality choices when the source provides them
🚀 Run the Twitter/X media scraper
- Choose one Target type.
- Fill in the matching tweet, profile, hashtag, or keyword field.
- Pick the media types you want.
- Set Media item limit, or leave it empty to get all available results until the source is exhausted.
- Start the Actor and open Media items in the dataset.
Use known tweet URLs and IDs to find media from those posts. Profiles, hashtags, and keyword searches find matching public media. The Actor returns source-hosted links. It does not download, change, or bundle the files.
⚙️ Input
Only fields for the chosen Target are used.
Input fields
| Field | Type | What it does |
|---|---|---|
target | string | Chooses tweets, profiles, hashtags, or keyword search. |
tweetTargets | string[] | Lists public tweet URLs or raw tweet IDs, one per line. Used for the Tweets target. |
replyScope | string | Includes no replies, direct replies, or all reply levels for tweet targets. |
profiles | string[] | Lists public handles such as @NASA, one per line. Used for the Profiles target. |
profileFilters | object | Holds optional filters for posts found through profiles. |
profileFilters.minLikes | integer | Keeps posts with at least this many likes. Leave empty for no likes filter. |
profileFilters.minReposts | integer | Keeps posts with at least this many reposts. Leave empty for no repost filter. |
profileFilters.minReplies | integer | Keeps posts with at least this many replies. Leave empty for no reply filter. |
profileFilters.authorVerification | string | Keeps any author, verified authors, or authors not marked as verified. |
profileFilters.language | string | Keeps a language code such as en, es, or fr. Leave empty for any language. |
hashtags | string[] | Lists hashtags such as #nasa, one per line. Used for the Hashtags target. |
keywords | string[] | Lists search keywords or phrases, one search per line. Used for Keyword Search. |
mediaTypes | string[] | Chooses images, videos, GIFs, or any mix of them. |
maxItems | integer | Stops after returning this many media items across the run. Leave empty to get all available results until the source is exhausted. |
Example input
This example is from a successful run with the prefilled tweet:
{"target": "tweets","tweetTargets": ["https://x.com/teslaownersSV/status/2004891561180758165"],"replyScope": "none","mediaTypes": ["image","video","gif"],"maxItems": 5}
🧾 Output
The output includes a link to the default dataset. Each saved media row uses the same shape. Fields may be null when Twitter/X does not give the value.
Output fields
| Field | Type | What it does |
|---|---|---|
results | string | Links to the saved media rows in the default dataset. |
mediaUrl | string | Main direct source-hosted image, video, or GIF URL. |
mediaType | string | Says whether the row is an image, video, or GIF. |
mediaIndex | integer | Gives the media position in the post, starting at 1. |
attachmentCount | integer or null | Gives the number of media attachments in the source post. |
mediaId | string or null | Gives the Twitter/X media ID when available. |
thumbnailUrl | string or null | Gives a source-hosted preview image URL. |
altText | string or null | Gives accessibility text added to the media. |
width | integer or null | Gives media width in pixels. |
height | integer or null | Gives media height in pixels. |
durationMs | integer or null | Gives video or GIF length in milliseconds. |
aspectRatio | string or null | Gives a video or GIF aspect ratio. |
contentType | string or null | Gives the media MIME type. |
videoVariants | object[] | Lists other source-hosted video choices from highest to lowest bitrate. |
videoVariants.url | string | Gives the direct URL for a video choice. |
videoVariants.bitrate | integer or null | Gives bitrate in bits per second. |
videoVariants.width | integer or null | Gives variant width in pixels. |
videoVariants.height | integer or null | Gives variant height in pixels. |
videoVariants.contentType | string or null | Gives the variant MIME type. |
target | string | Gives the submitted value that first found the media. |
targetType | string | Gives the target kind that first found the media. |
tweetId | string | Gives the source post ID. |
tweetUrl | string | Gives the public source post URL. |
conversationId | string or null | Gives the Twitter/X conversation ID. |
text | string or null | Gives readable source post text while preserving its meaning and entity-like literals, or null when unavailable. |
postedAt | string or null | Gives the date and time the post was published. |
language | string or null | Gives Twitter/X's language code for the post. |
postingSource | string or null | Gives the app or service used to publish the post. |
authorUsername | string or null | Gives the author's username without @. |
authorName | string or null | Gives the author's display name. |
authorProfileUrl | string or null | Gives the author's public profile URL. |
authorAvatarUrl | string or null | Gives the author's public avatar URL. |
authorVerified | boolean or null | Says whether Twitter/X marks the author as verified. |
engagement | object | Holds public counts for the source post. |
engagement.likes | integer or null | Gives the number of likes. |
engagement.retweets | integer or null | Gives the number of reposts. |
engagement.replies | integer or null | Gives the number of replies. |
engagement.views | integer or null | Gives the number of views. |
engagement.quotes | integer or null | Gives the number of quote posts. |
engagement.bookmarks | integer or null | Gives the number of bookmarks. |
profile | object or null | Holds more profile facts for media found through a profile target. |
profile.bio | string or null | Gives the public profile bio. |
profile.location | string or null | Gives the public profile location. |
profile.websiteUrl | string or null | Gives the public website linked from the profile. |
profile.followers | integer or null | Gives the follower count. |
profile.following | integer or null | Gives the number of followed accounts. |
profile.createdAt | string or null | Gives the account creation date and time. |
profile.posts | integer or null | Gives the total profile post count. |
profile.media | integer or null | Gives the total profile media post count. |
This complete row is from a successful current-beta run for a public tweet:
{"target": "2099538990923751694","targetType": "tweet","tweetId": "2099538990923751694","tweetUrl": "https://x.com/willianmatiola/status/2099538990923751694","authorUsername": "willianmatiola","authorName": "Willian Matiola","text": "Ainda não superei esse & que o @ptrzzni e eu desenhamos juntos. Construindo cada próxima versão em cima da ideia um do outro. Vale o ♥️ ou não? https://t.co/HdOQspvfDA","postedAt": "2026-09-14T16:41:17.000Z","mediaType": "video","mediaUrl": "https://video.twimg.com/amplify_video/2099538724182695936/vid/avc1/1080x1350/xVBQ8oUKe-xSPINl.mp4?tag=29","mediaIndex": 1,"attachmentCount": 1,"thumbnailUrl": "https://pbs.twimg.com/amplify_video_thumb/2099538724182695936/img/ooEUaLW3NVsINh2X.jpg","altText": null,"engagement": {"likes": 68,"retweets": 0,"replies": 6,"views": 1360,"quotes": 0,"bookmarks": 3},"conversationId": "2099538990923751694","authorProfileUrl": "https://x.com/willianmatiola","authorAvatarUrl": "https://pbs.twimg.com/profile_images/1905566107437551616/X7zkWb04_normal.jpg","authorVerified": false,"language": null,"postingSource": null,"mediaId": "2099538724182695936","width": 1080,"height": 1350,"durationMs": 5033,"aspectRatio": null,"contentType": "video/mp4","videoVariants": [{"url": "https://video.twimg.com/amplify_video/2099538724182695936/vid/avc1/1080x1350/xVBQ8oUKe-xSPINl.mp4?tag=29","bitrate": 10368000,"contentType": "video/mp4","width": 1080,"height": 1350},{"url": "https://video.twimg.com/amplify_video/2099538724182695936/vid/avc1/720x900/iVN0XJgpxgcKCpoB.mp4?tag=29","bitrate": 2176000,"contentType": "video/mp4","width": 720,"height": 900},{"url": "https://video.twimg.com/amplify_video/2099538724182695936/vid/avc1/480x600/Hjzpil7HVo9RTMWz.mp4?tag=29","bitrate": 950000,"contentType": "video/mp4","width": 480,"height": 600},{"url": "https://video.twimg.com/amplify_video/2099538724182695936/vid/avc1/320x400/BVWkMMjyOaU9_jhq.mp4?tag=29","bitrate": 632000,"contentType": "video/mp4","width": 320,"height": 400}],"profile": null}
💳 Pricing
Charges
This Actor uses pay-per-event pricing. You are charged for each direct link for a public image, video, or GIF that is saved to the dataset.
Use Media item limit to control the run size. Leaving it empty gets all available results until the source is exhausted.
🔌 Integrations
Ways to connect
Use the Apify API, schedules, webhooks, Make, Zapier, Google Sheets, or cloud storage. You can also export the dataset as JSON, CSV, Excel, XML, RSS, or HTML.
❓ FAQ
Can it get private or deleted media?
No. It only works with public Twitter/X content. It does not get private, protected, deleted, or age-gated content.
Do I need a Twitter/X login or API key?
No. You do not need to give the Actor a Twitter/X login, cookies, or API key.
Can I mix tweets, profiles, hashtags, and keywords in one run?
No. Choose one Target type for each run and fill in its matching field. Use another run for a different target type.
Can I choose images, videos, or GIFs?
Yes. Pick one type or any mix in Media types.
Can it include media from replies?
Yes, for tweet targets. Choose direct replies or all reply levels in Replies.
Does it save the media files?
No. It returns direct source-hosted links and data. It does not copy or change the files.
What happens when two targets find the same media?
The first eligible match is saved right away. Later matches for that same source media are ignored, so the saved row keeps only the first target that found it.
Is this a general Twitter scraper?
No. It saves rows only for the media types you ask for. It is not meant to collect posts with no requested media.
📝 Changelog
v0.3 (15-09-2026)
- Added attachment counts and richer details to saved media rows.
- Improved recovery from temporary Twitter/X access problems and clear reporting when a target still cannot be read.
v0.2
- Added media discovery from public profiles, hashtags, and keywords, with richer author, engagement, and video data.
v0.1
- Initial release.
🆘 Support
For issues, questions, or feature requests, file a ticket and I'll fix or implement it in less than 24h 🫡
🔗 Related Actors
- Twitter Scraper collects broader public post, profile, and trend data.
- Twitter Screenshot Generator turns public posts into clean screenshot images.
- Instagram Downloader API gets media links from public Instagram posts and reels.
- Facebook Media Downloader gets direct source-hosted links from public Facebook videos, reels, and photos.
- Telegram Media Downloader gets photos and videos from public Telegram posts and channels.
Made with ❤️ by Maxime Dupré