# Changelog of X (Twitter) Scraper: Tweets & Profiles by URL, No Login (`humble-echidna/x-scraper`) Actor

- **URL**: https://apify.com/humble-echidna/x-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/humble-echidna/x-scraper.md

## Changelog

Versions follow MAJOR.MINOR.PATCH (`src/version.py`); Apify shows MAJOR.MINOR from `.actor/actor.json`.
Every run logs its version and records it in the `RUN_STATS` key-value record.

### 0.1.2 (2026-10-16)

- A run that returns nothing (every input bad, private, blocked or unreachable, or an empty input) now ends
  SUCCEEDED with an empty dataset and the reason as its status message and in the log, instead of FAILED. Only an
  unexpected error still fails the run. `RUN_STATS` keeps the reason as before.
- No change to output fields or price.

### 0.1.1 (2026-10-15)

- A run where every line fails now shows the reason in its status message (e.g. "'#bitcoin' looks like a search; X
  shows search results only to logged-in accounts..."), not just "see log".
- Searches typed as lines (`#hashtag`, `$cashtag`, words with spaces, `from:user`) are refused with that reason
  instead of "isn't a tweet URL".
- Also read: `twitter.com/#!/NASA` links, `x.com/intent/user?screen_name=NASA` (and follow intents), links wrapped in
  `<...>` or quotes, and links carrying invisible characters (zero-width space, BOM) from chats and documents.
  `x.com/i/user/<number>` links say to give the @handle instead of the logged-in-only message.

### 0.1.0 (2026-10-14)

First release.

- Tweets by URL (x.com, twitter.com, mobile, `/i/status/`, fxtwitter-style links) or id, and profiles by URL or
  handle, mixed in one list; duplicates returned once.
- Tweets: full text (long posts included, t.co links expanded), likes, replies, retweets, quotes, bookmarks, views,
  photos, videos and GIFs with every MP4, polls, link cards, X Articles, quoted tweet, reply target, author.
  Profiles: bio, location, website, created, followers, following, posts, verification, picture, banner.
- Optional: a profile's latest posts (the 5 X shows logged out) and a tweet's top replies (the 3 X shows logged out).
- Source: what x.com serves a logged-out visitor: its web app's own API (guest token, the app's public bearer token;
  no account, cookie or login), the ids on its logged-out profile and tweet pages, and the embed CDN
  (cdn.syndication.twimg.com) as the fallback for tweets. Operation ids are re-learned from X's pages when X ships a
  new web app. None of these endpoints is documented for third parties.
- robots.txt and terms (read 2026-10-14): x.com/robots.txt disallows every crawler; X's Terms of Service (effective
  2026-10-09, https://x.com/tos) forbid crawling or scraping without written consent and set liquidated damages above
  1,000,000 posts in 24 hours. Built anyway on Michael's 2026-10-14 decision (X opened, platform robots.txt
  exception in mms_common); the README says both plainly.
- Search, hashtags, lists, follower lists and full timelines are refused per line with the reason: X shows them only
  to logged-in accounts.
- Charged per result returned (`apify-default-dataset-item`): failed lines and duplicates are free.
- "Max results per run" input (`maxItems` read too), and the maximum cost per run is honoured: once either is
  covered, lines still being fetched are cancelled and the rest are skipped (listed as `queriesSkipped` in
  `RUN_STATS`).
- Failure isolation: a failing line only affects itself.
