Twitter X Media Scraper avatar

Twitter X Media Scraper

Pricing

from $1.60 / 1,000 media links

Go to Apify Store
Twitter X Media Scraper

Twitter X 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

from $1.60 / 1,000 media links

Rating

0.0

(0)

Developer

Maxime Dupré

Maxime Dupré

Maintained by Community

Actor stats

0

Bookmarked

43

Total users

5

Monthly active users

9 days ago

Last modified

Share

Twitter X 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.

📊 What data does it return?

Each dataset row is one image, video, or GIF. If the same media appears through more than one target, the row keeps 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 best playable video link and other video quality choices

🚀 How to run the Actor

  1. Choose one Target type.
  2. Fill in the matching tweet, profile, hashtag, or keyword field.
  3. Pick the media types you want.
  4. Set Media item limit, or leave it empty to get all available results until the source is exhausted.
  5. Start the Actor and open Media items in the dataset.

Known tweet URLs and IDs get media from those posts. Profiles can cover public profile history up to your run limit. Hashtag and keyword searches find recent public posts. The Actor gives you links; it does not download, change, or bundle the files.

🎯 Input

Only fields for the chosen Target are used.

FieldTypeWhat it does
targetstringChooses tweets, profiles, hashtags, or keyword search.
tweetTargetsstring[]Lists public tweet URLs or raw tweet IDs, one per line. Used for the Tweets target.
replyScopestringIncludes no replies, direct replies, or all reply levels for tweet targets.
profilesstring[]Lists public handles such as @NASA, one per line. Used for the Profiles target.
profileFiltersobjectHolds optional filters for posts found through profiles.
profileFilters.minLikesintegerKeeps posts with at least this many likes. Leave empty for no likes filter.
profileFilters.minRepostsintegerKeeps posts with at least this many reposts. Leave empty for no repost filter.
profileFilters.minRepliesintegerKeeps posts with at least this many replies. Leave empty for no reply filter.
profileFilters.authorVerificationstringKeeps any author, verified authors, or authors not marked as verified.
profileFilters.languagestringKeeps a language code such as en, es, or fr. Leave empty for any language.
hashtagsstring[]Lists hashtags such as #nasa, one per line. Used for the Hashtags target.
keywordsstring[]Lists search keywords or phrases, one search per line. Used for Keyword Search.
mediaTypesstring[]Chooses images, videos, GIFs, or any mix of them.
maxItemsintegerStops after this many saved media items across the run. Leave empty to get all available results until the source is exhausted.

This example is from a successful run with the prefilled tweet:

{
"target": "tweets",
"tweetTargets": [
"https://x.com/teslaownersSV/status/2004891561180758165"
],
"replyScope": "direct",
"mediaTypes": [
"image",
"video",
"gif"
],
"maxItems": 5
}

📄 Output

All media types use the same row shape. Fields may be null when Twitter/X does not give the value.

FieldTypeWhat it does
mediaUrlstringMain direct source-hosted image, video, or GIF URL.
mediaTypestringSays whether the row is an image, video, or GIF.
mediaIndexintegerGives the media position in the post, starting at 1.
mediaIdstring or nullGives the Twitter/X media ID when available.
thumbnailUrlstring or nullGives a source-hosted preview image URL.
altTextstring or nullGives accessibility text added to the media.
widthinteger or nullGives media width in pixels.
heightinteger or nullGives media height in pixels.
durationMsinteger or nullGives video or GIF length in milliseconds.
aspectRatiostring or nullGives a video or GIF aspect ratio.
contentTypestring or nullGives the media MIME type.
videoVariantsobject[]Lists other source-hosted video choices from highest to lowest bitrate.
videoVariants.urlstringGives the direct URL for a video choice.
videoVariants.bitrateinteger or nullGives bitrate in bits per second.
videoVariants.widthinteger or nullGives variant width in pixels.
videoVariants.heightinteger or nullGives variant height in pixels.
videoVariants.contentTypestring or nullGives the variant MIME type.
targetstringGives the submitted value that first found the media.
targetTypestringGives the target kind that first found the media.
tweetIdstringGives the source post ID.
tweetUrlstringGives the public source post URL.
conversationIdstring or nullGives the Twitter/X conversation ID.
textstring or nullGives the source post text.
postedAtstring or nullGives the date and time the post was published.
languagestring or nullGives Twitter/X's language code for the post.
postingSourcestring or nullGives the app or service used to publish the post.
authorUsernamestring or nullGives the author's username without @.
authorNamestring or nullGives the author's display name.
authorProfileUrlstring or nullGives the author's public profile URL.
authorAvatarUrlstring or nullGives the author's public avatar URL.
authorVerifiedboolean or nullSays whether Twitter/X marks the author as verified.
engagementobjectHolds public counts for the source post.
engagement.likesinteger or nullGives the number of likes.
engagement.retweetsinteger or nullGives the number of reposts.
engagement.repliesinteger or nullGives the number of replies.
engagement.viewsinteger or nullGives the number of views.
engagement.quotesinteger or nullGives the number of quote posts.
engagement.bookmarksinteger or nullGives the number of bookmarks.
profileobject or nullHolds more profile facts for media found through a profile target.
profile.biostring or nullGives the public profile bio.
profile.locationstring or nullGives the public profile location.
profile.websiteUrlstring or nullGives the public website linked from the profile.
profile.followersinteger or nullGives the follower count.
profile.followinginteger or nullGives the number of followed accounts.
profile.createdAtstring or nullGives the account creation date and time.
profile.postsinteger or nullGives the total profile post count.
profile.mediainteger or nullGives the total profile media post count.

This complete row comes from a successful profile run:

{
"target": "@NASA",
"targetType": "profile",
"tweetId": "2081772453093593253",
"tweetUrl": "https://x.com/NASA/status/2081772453093593253",
"authorUsername": "NASA",
"authorName": "NASA",
"text": "This August, our astronauts will be stepping outside the @Space_Station three times! NASA experts will discuss our upcoming spacewalks at 2pm ET (1800 UTC) on July 30. Learn how to tune in: https://t.co/7CyQqEN9bF https://t.co/Dxa5zMAxzh",
"postedAt": "2026-07-27T16:03:24.000Z",
"mediaType": "image",
"mediaUrl": "https://pbs.twimg.com/media/HOPxABqXMAAvEjg.jpg",
"mediaIndex": 1,
"thumbnailUrl": "https://pbs.twimg.com/media/HOPxABqXMAAvEjg.jpg",
"altText": "A photo of NASA astronaut Jessica Meir's reflection in a spacesuit helmet visor as she swaps and installs parts. Credit: NASA/Jack Hathaway",
"engagement": {
"likes": 666,
"retweets": 84,
"replies": 82,
"views": 250921,
"quotes": 6,
"bookmarks": 28
},
"conversationId": "2081772453093593253",
"authorProfileUrl": "https://x.com/NASA",
"authorAvatarUrl": "https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg",
"authorVerified": true,
"language": "en",
"postingSource": null,
"mediaId": "2081772435523710976",
"width": 8192,
"height": 5461,
"durationMs": null,
"aspectRatio": null,
"contentType": null,
"videoVariants": [],
"profile": {
"bio": "Making the seemingly impossible, possible. ✨",
"location": null,
"websiteUrl": "http://www.nasa.gov/",
"followers": 92217924,
"following": 119,
"createdAt": "2007-12-19T20:20:32.000Z",
"posts": 74256,
"media": 28047
}
}

💸 Pricing

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. A target with no saved media link does not create this event.

Use Media item limit to control the run size. Leaving it empty gets all available results until the source is exhausted.

🔌 Integrations

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 Twitter/X credentials.

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

  • 0.2: Added media discovery from public profiles, hashtags, and keywords, with richer author, engagement, and video data.
  • 0.1: Initial release.

🆘 Support

For issues, questions, or feature requests, file a ticket and I'll fix or implement it in less than 24h 🫡

Made with ❤️ by Maxime Dupré