x-tweet-fetcher

ythx-101MIT活跃维护

无需登录或 API Key 就能抓取 X/Twitter 的推文、回复、时间线和长文,给 AI Agent 和自动化流程提供数据来源。

Fetch X/Twitter tweets, replies, timelines, and articles without login or API keys — field tool for AI agents.

v3.0.0发布于 2026-07-05 17:39 UTC1,003star +2 / 7 天83fork同步于 2026-11-10 23:52 UTC

怎么上手

由 README 提炼,执行前请确认
git clone https://github.com/ythx-101/x-tweet-fetcher
cd x-tweet-fetcher && pip install .
xtf --url https://x.com/user/status/1234567890
硬件要求按 README 说明

README 未说明硬件要求;浏览器后端需本地运行 Camofox(默认 localhost:9377)或 Playwright,时间线与搜索需可访问的 Nitter 实例。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

无需登录或 API Key 即可抓取 X/Twitter 推文、回复、时间线与文章,为 AI Agent 提供统一 JSON 输出

无需登录或 API Key 就能抓取 X/Twitter 的推文、回复、时间线和长文,给 AI Agent 和自动化流程提供数据来源。

核心能力

  • 用 fxtwitter、Nitter、浏览器三后端自动回退路由
  • 单条推文零依赖即可抓取,时间线走 Nitter 直连 HTTP
  • 浏览器后端支持列表与 X Article 全文抓取
  • 所有后端归一为统一 Tweet/Reply/Profile/Article schema
  • 用 --ledger 将抓取结果去重归档到 SQLite 并可离线查询

容易踩的坑

时间线、搜索、回复依赖 Nitter 实例,公共实例常失效,建议自托管并设置 XTF_NITTER;列表与文章必须走浏览器后端,需先装 Camofox 或 pip install ".[playwright]" 并设 XTF_BROWSER=playwright;从 v1 迁移时 --search 的每条推文字段已改为与 --user 统一,url/has_media/media_urls 被移除。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v3.0.0
  1. v3.0.0v3.0.0 — installable xtf package最新正式版2026-07-05 · 2026-07-05 17:39 UTC

    Full restructure — same CLI, new internals. The scripts/ monolith is now an installable package: pip install x-tweet-fetcher → xtf command + from xtf import Router.

    Highlights

    • Unified backend protocol (fxtwitter / nitter / browser) behind an auto-fallback router
    • Unified Tweet/Reply/Profile/Article models across all backends — one JSON schema downstream
    • Machine-readable errors: every failure carries error_code (+ per-backend error_causes); unreachable backends give a clear error with exit 1, never silent empty results
    • Multi-instance Nitter with health-check and failover: XTF_NITTER=url1,url2
    • Retry with exponential backoff for transient 429/5xx/network failures
    • Fixture-locked test suite (67 tests, real captured Nitter pages) + CI

    Breaking changes

    • --search per-tweet schema is unified with --user: author/author_name/time_ago replace username/display_name/time; url/has_media/media_urls dropped. See MIGRATION.md.
    • Repo scope narrowed to tweet fetching. Analytics / China-platform / Obsidian scripts removed — the old world is preserved at the v1-legacy tag.
    • No more hardcoded public-Nitter default; configure your own via XTF_NITTER.

    Compatibility

    • python3 scripts/fetch_tweet.py still works (thin shim), all flags and exit codes unchanged
    • NITTER_URL (v1 env var) still honored
    • v1 mentions cache read as-is

    Why v3.0.0: the v2.x tags on this repo were monolith releases; the package restructure gets a clean major.

    🤖 Generated with Claude Code

  2. v2.0.0v2.0.0 — Three Backends, Self-hosted Nitter, Keyword Search2026-03-23 · 2026-03-23 14:53 UTC
    查看更新说明

    🦞 v2.0.0 — Smart Backend Routing

    ✨ New Features

    • Three backend modes: --backend nitter|browser|auto (default: auto)
      • nitter: Zero dependency, Python stdlib only. Timeline, search, replies, profile, mentions
      • browser: Playwright/Chromium. Full features including Lists, Articles, fetch_china
      • auto: Tries Nitter first, falls back to browser automatically
    • Self-hosted Nitter backend (nitter_client.py): Pure stdlib HTTP client for local Nitter instance
      • Timeline fetching with pagination
      • Real-time keyword search — search any keyword across X via self-hosted Nitter
      • User profile/stats
      • Single tweet + replies
      • RSS feed support
    • Playwright override: OpenClaw built-in Chromium auto-detected, no extra install
    • invoke.sh v6: SSH direct-call to full-blood Claude Code (no Bridge bottleneck)

    🔧 Improvements

    • 21 code review issues fixed (critical: missing imports, runtime errors; medium: backend routing)
    • Removed Camofox/Playwright hard dependency — browser is now optional fallback
    • supplement_views() migrated from requests to urllib (zero deps)
    • x-profile-analyzer.py respects passed model/api_url params
    • Version strings unified to v1.5 across x-profile-analyzer
    • Dead code cleanup across 6 files

    📖 Docs

    • README v3: Three backend architecture, auto fallback diagram, environment compatibility matrix
    • Self-hosted Nitter 5-minute setup guide
    • Security: bind 127.0.0.1 only, secondary account, session tokens ~1 year

    ⚠️ Known Limitations

    • X Lists: GraphQL API returns empty data (X upstream change, affects all clients including Nitter)
    • X Articles: Nitter never supported, requires browser backend
    • Public Nitter instances: All dead/403 as of March 2026 — self-host is the only option

    🙏 Credits

    • zedeus/nitter — the self-hosted Twitter frontend (12.6k ⭐)
    • FxTwitter — public API for single tweets
    • Community PRs: Tavily search, article image inline, Obsidian export
  3. v1.9.0v1.9.0 — Obsidian Export — X Articles + arXiv Papers → Local Knowledge Base2026-03-20 · 2026-03-20 05:41 UTC
    查看更新说明

    v1.9.0 — Obsidian Export — X Articles + arXiv Papers → Local Knowledge Base

    Released on 2026-03-20.

    New Features

    • X → Obsidian export — save X/Twitter articles as Obsidian Markdown with locally downloaded images (community PR by @andrewy-wizard) (62c50cc)
    • Paper → Obsidian export — convert arXiv papers to Obsidian-ready Markdown (2d028b8)
      • Fetches HTML from ar5iv (LaTeXML) + metadata from arXiv API
      • Downloads all figures to local assets/ directory
      • Preserves LaTeX math formulas ($...$ inline, $$...$$ block)
      • Converts tables to Markdown format
      • YAML frontmatter with title, authors, date, arxiv_id, tags
      • Tested on: Attention Is All You Need, Chain-of-Thought, ViT, TinyLlama
      • Supports --arxiv, --url, --html input modes
      • Zero external dependencies

    Docs

    • add Paper → Obsidian section to README with usage examples (f0a76a7)
    • update capabilities table with Paper → Obsidian row

    Community

    • Merged PR #55 from @andrewy-wizard (X to Obsidian export with local assets)

    Full Changelog: https://github.com/ythx-101/x-tweet-fetcher/compare/v1.8.0...v1.9.0

  4. v1.8.0v1.8.0 — Academic Paper Mode — Author X Finder + Paper Recommendations2026-03-19 · 2026-03-19 14:43 UTC
    查看更新说明

    v1.8.0 — Academic Paper Mode — Author X Finder + Paper Recommendations

    Released on 2026-03-19.

    New Features

    • add --github entry point — extract authors from README BibTeX, zero ArXiv dependency (3274c62)
    • direct X profile URLs + 3s search delay + CC review fixes (8d28103)
    • output direct X/Twitter profile URLs instead of @handles (31aa35d)
    • two-phase GitHub lookup — guess first, then HTML search (146a952)
    • Camofox browser as ultimate search fallback (636f263)
    • Brave HTML scraping as primary search engine for Twitter lookup (21816a9)
    • SearxNG-first search + profile URL guessing bypass 429 (4c7d90c)
    • bypass GitHub 429 — profile URL guessing instead of search (c22126f)
    • arxiv_author_finder zero-token — GitHub API → HTML scraping (32a65f6)
    • source paper author Twitter lookup via arxiv_author_finder pipeline (029c426)
    • remove GitHub API dependency — zero tokens needed (6a2762a)
    • OpenAlex as primary engine — zero API key, zero rate limit (fdc6028)
    • Academic Paper Mode — paper recommendations + author Twitter finder (5d8460e)
    • add --verify flag for AI-powered freshness validation (3e56e03)

    Bug Fixes

    • Auto-review: issues found in recent push (#53) (61080f7)
    • remove Mac Bridge, add GitHub API fallback, improve name matching (bcc3a27)
    • trust links not names — remove username guessing, add search result verification (1afee0a)
    • CC review — XXE protection, NameError guard, runtime cap (389a7dc)
    • bypass GitHub search 429 with 5s delay — search all authors (4367e70)
    • Auto-review: issues found in recent push (#48) (059f1de)
    • Auto-review: issues found in recent push (#46) (7dba571)
    • Auto-review: issues found in recent push (#44) (69d4a5b)
    • CC review round 4 — XXE protection, --top bounds, double fetch, dedup (d7d48de)
    • handle papers not yet in databases + catastr
  5. v1.7.0v1.7.0 — X-Tracker — 推文爆点检测2026-03-14 · 2026-03-14 03:12 UTC
    查看更新说明

    v1.7.0 — X-Tracker — 推文爆点检测

    Released on 2026-03-14.

    New Features

    • X-Tracker: 推文增长追踪器,借鉴半导体 ETCH Endpoint Detection 算法 (2257054)
      • 双频采样:新推文 (<48h) 每 15 分钟,老推文每小时
      • ETCH 导数检测 + 滑窗平均(5 样本窗口,所有增速归一化到 per-hour)
      • 多信号融合:浏览×1 + 赞×1 + 收藏×1.5 + 转发×3 加权评分
      • 爆点确认:连续 3 窗口超阈值,或单窗口 +100%/h 直接触发
      • 饱和检测:连续 6 样本增速 < 2%/h → 长尾
      • 爆点时间窗口精确定位 + 传播模式分析(大V驱动 vs 算法推荐)
      • 同时段话题交叉分析(调用 x_discover 搜索)
      • 文件锁 (fcntl) 防双频 cron 冲突 + 原子写入

    Bug Fixes

    • 支持中文关键词提取(话题交叉分析中英文混合标签正确切分)(2b40f5b)

    Usage

    # 添加追踪
    python3 tweet_growth_cli.py --add "https://x.com/.../status/123" "标签"
    
    # 列出追踪
    python3 tweet_growth_cli.py --list
    
    # 采样(cron)
    */15 * * * * python3 tweet_growth_cli.py --run --fast    # 新推文
    0 * * * *    python3 tweet_growth_cli.py --run --normal  # 老推文
    
    # 分析报告
    python3 tweet_growth_cli.py --report TWEET_ID [--cross]
    

    New Files

    • scripts/tweet_growth.py — 核心模块
    • scripts/tweet_growth_cli.py — CLI 入口
    • scripts/growth_config.py — 配置中心

    Full Changelog: https://github.com/ythx-101/x-tweet-fetcher/compare/v1.6.3...v1.7.0

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    x-tweet-fetcher

    Fetch X/Twitter tweets, replies, timelines, lists, and articles — no login, no API keys.

    License: MIT Python 3.10+ GitHub stars

    Three backends · Auto fallback · Unified JSON schema · Built for AI agents

    Quick Start · Backends · Capabilities · Python API · Self-hosted Nitter · Migrating from v1


    😤 Problem

    You: fetch that tweet / list / article for me
    AI:  I can't access X/Twitter. Please copy-paste the content manually.
    
    You: ...seriously?
    

    X has no free API. Scraping gets you blocked. Browser automation is fragile in headless environments.

    x-tweet-fetcher solves this with smart backend routing: FxTwitter for single tweets (zero deps), Nitter for timelines and search (direct HTTP), a browser driver for everything else — with automatic fallback between them.

    🚀 Quick Start

    git clone https://github.com/ythx-101/x-tweet-fetcher
    cd x-tweet-fetcher && pip install .
    
    # Single tweet — works instantly, zero configuration
    xtf --url https://x.com/user/status/1234567890
    
    # User timeline (needs a Nitter instance, see below)
    export XTF_NITTER=http://127.0.0.1:8788
    xtf --user elonmusk --limit 20
    
    # Search
    xtf --search "openclaw" --limit 10
    
    # Human-readable output instead of JSON
    xtf --user elonmusk --text-only
    

    Prefer not to install? python3 scripts/fetch_tweet.py --url ... works straight from the clone (same flags).

    🔀 Three Backends

    BackendDepsSpeedCovers
    fxtwitterNone (stdlib)⚡⚡Single tweets, user profiles
    nitterA Nitter instance⚡Timeline, search, replies, mentions
    browserCamofox or Playwright🐢Everything above + Lists + X Articles
    auto (default)Best available⚡→🐢Nitter first, browser fallback
    xtf --user elonmusk                    # auto (default)
    xtf --user elonmusk --backend nitter   # direct HTTP only
    xtf --list 1455045069516357634         # lists always use the browser
    

    Browser driver defaults to Camofox (localhost:9377). Playwright users:

    pip install ".[playwright]"            # from the clone
    export XTF_BROWSER=playwright          # or: --browser-driver playwright
    

    📊 Capabilities

    FeatureFlagBackend
    Single tweet (text, stats, media, quotes)--urlfxtwitter
    Reply comments (threaded)--url --repliesnitter / browser
    User timeline (paginated)--usernitter / browser
    Search--searchnitter
    User profile--user-infofxtwitter → nitter
    X List tweets--listbrowser
    X Article full text--articlebrowser
    Mentions monitor (incremental, cron-friendly)--monitornitter / browser
    Archive fetch results (dedupe, SQLite)--ledger <db>any
    Search / stats the archive (offline)--ledger <db> --query/--statsoffline

    Exit codes (cron-friendly): 0 success / no new mentions · 1 error / new mentions found · 2 monitor setup error.

    Errors are machine-readable. Every failure carries error (human message) plus error_code — one of invalid_input, not_found, rate_limited, upstream_down, backend_unavailable, all_backends_failed — so agents can branch on it. all_backends_failed additionally includes per-backend error_causes.

    📚 推文库 (Ledger)

    --ledger <db> turns xtf into a fetch + archive + query local tweet library: every timeline / search / list / replies / single-tweet fetch is archived into a SQLite DB, deduped by tweet_id (INSERT OR IGNORE, idempotent). Schema is compatible with the tweet-ledger (OpenClaw) tweets table, so the same DB can be read by both tools.

    # Fetch + archive a timeline
    xtf --user YuLin807 --limit 20 --ledger ~/tweets.db
    
    # Search the archive (offline)
    xtf --ledger ~/tweets.db --query "sop"
    
    # Stats: totals, languages, media/urls, time ranges
    xtf --ledger ~/tweets.db --stats
    

    Behavior without --ledger is unchanged (3.0.0-compatible). Archiving never breaks a successful fetch — on failure the JSON envelope carries ledger_error instead. Single-tweet (fxtwitter) dicts lack tweet_id, so the CLI injects it from the URL; --replies results are archived with is_reply=1 and in_reply_to_status_id pointing at the parent tweet.

    tweets table: tweet_id (PK) · created_at · full_text · lang · source_file · is_reply · in_reply_to_status_id · retweeted_status_id · quoted_status_id · urls_json · media_json · raw_json · imported_at

    End-to-end integration test record: docs/e2e-integration.md.

    🐍 Python API

    from xtf import Router, NotFound, RateLimited
    
    router = Router()                                  # backend="auto"
    tweet   = router.fetch_tweet("user", "1234567890") # dict, v1-compatible shape
    tweets  = router.fetch_timeline("user", limit=20)  # list[Tweet]
    replies = router.fetch_replies("user", "1234567890")
    results = router.search("openclaw", limit=10)
    
    for tw in tweets:
        print(tw.author, tw.likes, tw.text)
        print(tw.to_dict())                            # JSON-ready
    

    All backends normalize into one Tweet / Reply / Profile / Article schema — your downstream prompt only ever needs to describe one shape.

    ⚙️ Configuration

    Everything is an environment variable (CLI flags override):

    VariableDefaultMeaning
    XTF_NITTERhttp://127.0.0.1:8788Comma-separated Nitter instances, tried in order with failover
    XTF_BROWSERcamofoxBrowser driver: camofox or playwright
    XTF_BROWSER_PORT9377Camofox HTTP port
    XTF_LANGzhMessage language: zh or en
    XTF_CACHE_DIR~/.x-tweet-fetcherMentions-monitor cache

    NITTER_URL (the v1 name) is still honored as a fallback for XTF_NITTER.

    🏗 Self-hosted Nitter

    Public Nitter instances are unreliable and frequently dead. Self-hosting is strongly recommended for timeline/search/replies:

    # See https://github.com/zedeus/nitter for full setup
    docker run -d -p 8788:8080 --name nitter zedeus/nitter:latest
    export XTF_NITTER=http://127.0.0.1:8788
    

    Multiple instances failover automatically:

    export XTF_NITTER=http://127.0.0.1:8788,https://your-backup-instance.example
    

    If no instance is reachable, you get a clear error (error_code: "all_backends_failed", with each backend's reason — e.g. backend_unavailable — under error_causes) telling you exactly what to set. Never a silent empty result.

    📁 Project Structure

    src/xtf/
    ├── models.py        # Tweet / Reply / Profile / Article dataclasses
    ├── backends/
    │   ├── fxtwitter.py # single tweets + profiles
    │   ├── nitter.py    # direct HTTP, multi-instance failover
    │   └── browser.py   # Camofox / Playwright snapshot fetching
    ├── parsers/         # pure functions, locked by fixture tests
    ├── router.py        # auto-fallback chain
    ├── monitor.py       # incremental mentions monitor
    └── cli.py           # the `xtf` command
    scripts/fetch_tweet.py   # v1-compatible entry point (thin shim)
    tests/fixtures/          # captured page structures — regression protection
    

    🔄 Migrating from v1

    python3 scripts/fetch_tweet.py still works with all v1 flags and exit codes, and JSON fields are unchanged for every mode except --search, whose per-tweet schema is now unified with --user (fields renamed, url/has_media/media_urls dropped). See MIGRATION.md for the full list, including where the analytics/China/Obsidian scripts went (spoiler: their own repos — this project is now purely about fetching tweets; the old world lives at the v1-legacy tag).

    🧪 Development

    pip install -e ".[dev]"
    pytest          # all parsers locked by fixture tests
    ruff check src tests
    

    When Nitter or X change their page structure, capture a fresh snapshot into tests/fixtures/ — the failing test will show exactly which parser and field broke.

    🙏 Acknowledgments

    • Nitter by zedeus — self-hosted Twitter frontend
    • FxTwitter — public API for single tweet data
    • Camofox — anti-fingerprint browser, default browser driver
    • Playwright — alternative browser automation driver
    • OpenClaw — AI agent framework this tool grew up in

    📜 License

    MIT


    Three backends. Auto fallback. Built for AI agents.

    GitHub · Issues · #22 Teahouse · Agent Waystation