Agent skill

Twitter X Scraping

by swyxio in swyxio/skills

A skill your agent uses when scraping public Twitter/X timelines or lists through Nitter-style mirrors with axios and Playwright fallback, including anti-bot challenge handling and pagination limits.

MITAuto-check passedData & Analytics

Install Twitter X Scraping

skills CLI
$ npx skills add swyxio/skills --skill twitter-x-scraping -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install swyxio/skills twitter-x-scraping --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/swyxio/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/twitter-x-scraping .claude/skills/twitter-x-scraping && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
twitter-x-scraping
GitHub stars
176
Token cost
~3.5k tokens
SKILL.md length
677 words
Files
1
Skills in repo
89
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when scraping public Twitter/X timelines or lists through Nitter-style mirrors with axios and Playwright fallback, including anti-bot challenge handling and pagination limits.

  • Works in 7 steps: URL Structure → Fetch Strategy: axios → Playwright… → Browser Anti-bot Bypass → …
  • Scraping public Twitter/X timelines
  • SKILL.md covers Core Methodology, Quick-Start: Minimal…, Empirical Findings (Apr 2026) and Dependencies, plus 1 more section
  • Calls npx; reaches nitter.net and pbs.twimg.com

What it does

Twitter X Scraping is an agent skill from swyxio/skills. Use when scraping public Twitter/X timelines or lists through Nitter-style mirrors with axios and Playwright fallback, including anti-bot challenge handling and pagination limits.

Its SKILL.md is about 3.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Data & Analytics, covering Web scraping and Browser testing. It works with X (Twitter) and Playwright. The repository describes itself as: Agent skills for Claude Code and other AI agents. The licence is MIT.

When your agent uses it

  • Scraping public Twitter/X timelines
  • Lists through Nitter-style mirrors with axios and Playwright fallback
  • Including anti-bot challenge handling and pagination limits

Example prompts

  • “/twitter-x-scraping”

Requirements

  • Node.js

Workflow steps

7 steps, taken from the step headings in SKILL.md.

  1. URL Structure
  2. Fetch Strategy: axios → Playwright fallback
  3. Browser Anti-bot Bypass
  4. Retry Logic with Backoff
  5. HTML Parsing with Cheerio
  6. Cursor-Based Pagination
  7. Date-Bounded Stopping

What it can do on your machine

Read from SKILL.md and the folder at commit 038ef34. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • nitter.net
    • pbs.twimg.com

    Also links to:

    • status.d420.de

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Twitter X Scraping loads about 3.5k tokens when it runs. Until then it costs about 50 tokens; SKILL.md has 677 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~50
When it runs · the whole SKILL.md, loaded when a task matches
~3.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from swyxio/skills at commit 038ef34, republished under its MIT licence (© swyxio). 677 words, ~3,477 tokens.

Download SKILL.mdSave it as .claude/skills/twitter-x-scraping/SKILL.md (or your agent's skills folder).
name
twitter-x-scraping
description
Use when scraping public Twitter/X timelines or lists through Nitter-style mirrors with axios and Playwright fallback, including anti-bot challenge handling and pagination limits.

Skill: Scraping Nitter.net for Tweets

This codebase scrapes nitter.net — an open-source Twitter frontend — to collect tweets from a list or profile within a time window. The technique works without a Twitter API key.

Core Methodology

1. URL Structure

Nitter mirrors Twitter's URL layout:

TargetNitter path
Twitter List/i/lists/<listId>
User Profile/<handle>
Paginatedappend ?cursor=<cursor>
2. Fetch Strategy: axios → Playwright fallback

Start with plain HTTP (axios). If nitter serves an anti-bot challenge page (detected by the string "Verifying your request" in the HTML), permanently switch to a headed Playwright/Chrome session for the rest of the run.

ts
// challengeSolver.ts — detect challenge
const CHALLENGE_MARKER = 'Verifying your request';
export function isChallengePage(html: string): boolean {
  return html.includes(CHALLENGE_MARKER);
}

// scrapeNitterList.ts — switch modes on detection
if (isChallengePage(html)) {
  useBrowserMode = true;
  const browserHtml = await fetchWithBrowser(url, debug);
  return { html: browserHtml, url };
}
3. Browser Anti-bot Bypass

When challenge is detected, launch a real system Chrome (not headless) with automation signals suppressed:

ts
import { chromium } from 'playwright';

const browser = await chromium.launch({
  channel: 'chrome',
  headless: false,
  args: ['--disable-blink-features=AutomationControlled'],
});

const context = await browser.newContext({ locale: 'en-US' });
await context.addInitScript(() => {
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
});

const page = await context.newPage();
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });

// Wait for challenge to auto-resolve
await page.waitForSelector('.timeline-item', { timeout: 30000 });
const html = await page.content();

Key: reuse a single browser/page instance across all subsequent fetches (singleton pattern) — don't re-launch per page.

4. Retry Logic with Backoff

For HTTP 429 / 502 / 503, retry up to 10 times with exponential backoff (2s base, max 60s), respecting Retry-After and X-Rate-Limit-Reset headers:

ts
const maxRetries = 10;
const baseDelayMs = 2000;

for (let attempt = 0; attempt <= maxRetries; attempt++) {
  const res = await axios.get(url, {
    headers: FETCH_HEADERS,
    timeout: 30000,
    validateStatus: (s) => (s >= 200 && s < 400) || s === 429 || s === 502 || s === 503,
  });

  if (res.status === 429 || res.status === 502 || res.status === 503) {
    const ra = res.headers['retry-after'];
    if (ra && /^\d+$/.test(ra)) {
      await sleep(Math.min((parseInt(ra) + 2) * 1000, 5 * 60 * 1000));
      continue;
    }
    const jitter = Math.floor(Math.random() * 250);
    const waitMs = Math.min(baseDelayMs * Math.pow(2, attempt) + jitter, 60_000);
    await sleep(waitMs);
    continue;
  }

  if (res.status === 200) return res.data;
}

Use a browser-like User-Agent header:

ts
const FETCH_HEADERS = {
  'User-Agent': 'Mozilla/5.0 (compatible; MyBot/1.0) Node.js',
  'Accept-Language': 'en-US,en;q=0.9',
  'Accept': 'text/html,application/xhtml+xml',
  'Accept-Encoding': 'gzip, compress, deflate, br',
};
5. HTML Parsing with Cheerio

Nitter renders server-side HTML. Parse it with cheerio (jQuery-like API):

ts
import * as cheerio from 'cheerio';

const $ = cheerio.load(html);

// All tweets on the page
const $items = $('.timeline .timeline-item').filter((_, el) =>
  $(el).find('.tweet-body').length > 0
);

$items.each((_, el) => {
  const $el = $(el);

  // Tweet URL and ID
  const href = $el.find('a.tweet-link').first().attr('href'); // e.g. "/user/status/12345"
  const id = href?.match(/status\/(\d+)/)?.[1];

  // Timestamp — from the `title` attribute of the date link
  const title = $el.find('.tweet-date a').attr('title'); // e.g. "Apr 15, 2026 · 10:00 AM UTC"
  const timestamp = new Date(title?.replace(/\s*[·•]\s*/g, ' ') ?? '');

  // Tweet text
  const text = $el.find('.tweet-content.media-body').text().trim();

  // Author
  const username = $el.find('.tweet-header a.username').attr('title');
  const displayName = $el.find('.tweet-header a.fullname').attr('title');

  // Images
  $el.find('.attachments .attachment.image').each((_, img) => {
    const src = $(img).find('img').attr('src');  // relative URL
    const fullSrc = `https://nitter.net${src}`;
  });

  // Engagement stats
  $el.find('.tweet-stats .tweet-stat').each((_, stat) => {
    const icon = $(stat).find('.icon-container > span').attr('class') ?? '';
    const n = parseInt($(stat).text().replace(/\D/g, '') || '0');
    if (icon.includes('icon-heart')) console.log('likes:', n);
    if (icon.includes('icon-retweet')) console.log('retweets:', n);
  });

  // Is a retweet?
  const retweetedBy = $el.find('.retweet-header').text().trim() || undefined;

  // Quoted tweet
  const $quote = $el.find('.quote').first();
  if ($quote.length) {
    const quoteText = $quote.find('.quote-text').text().trim();
    const quoteUser = $quote.find('.tweet-name-row a.username').text().trim();
  }
});
6. Cursor-Based Pagination

Nitter exposes a "show more" link with a ?cursor= param:

ts
function findNextCursor($: cheerio.CheerioAPI): string | undefined {
  const href = $('div.show-more a').last().attr('href') ?? '';
  const m = href.match(/[?&]cursor=([^&]+)/);
  return m ? decodeURIComponent(m[1]) : undefined;
}

// In the pagination loop:
let cursor: string | undefined;
while (pagesFetched < maxPages) {
  const url = `https://nitter.net/i/lists/${listId}${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ''}`;
  const html = await fetchPage(url);
  const $ = cheerio.load(html);
  // ... parse tweets ...
  const next = findNextCursor($);
  if (!next) break;
  cursor = next;
}
7. Date-Bounded Stopping

Stop pagination as soon as the oldest non-retweet on a page is older than startDate, avoiding unnecessary fetches:

ts
// After parsing all tweets on a page:
const oldestNonRTMs = Math.min(
  ...pageTweets.filter(t => !t.retweetedBy).map(t => t.timestampMs)
);

if (oldestNonRTMs < startDate.getTime()) {
  console.log('Reached tweets older than start date; stopping.');
  break;
}

Quick-Start: Minimal End-to-End Example

ts
import axios from 'axios';
import * as cheerio from 'cheerio';

const LIST_ID = '1585430245762441216';
const BASE = 'https://nitter.net';
const HEADERS = {
  'User-Agent': 'Mozilla/5.0 (compatible; MyBot/1.0) Node.js',
  'Accept': 'text/html,application/xhtml+xml',
};

async function scrapeListPage(cursor?: string) {
  const url = `${BASE}/i/lists/${LIST_ID}${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ''}`;
  const res = await axios.get(url, { headers: HEADERS, timeout: 30000 });
  const $ = cheerio.load(res.data);

  const tweets: { id: string; text: string; timestamp: string }[] = [];

  $('.timeline .timeline-item').filter((_, el) =>
    $(el).find('.tweet-body').length > 0
  ).each((_, el) => {
    const $el = $(el);
    const href = $el.find('a.tweet-link').first().attr('href') ?? '';
    const id = href.match(/status\/(\d+)/)?.[1] ?? href;
    const title = $el.find('.tweet-date a').attr('title') ?? '';
    const timestamp = new Date(title.replace(/\s*[·•]\s*/g, ' ')).toISOString();
    const text = $el.find('.tweet-content.media-body').text().trim();
    tweets.push({ id, text, timestamp });
  });

  const nextHref = $('div.show-more a').last().attr('href') ?? '';
  const nextCursor = nextHref.match(/[?&]cursor=([^&]+)/)?.[1];

  return { tweets, nextCursor: nextCursor ? decodeURIComponent(nextCursor) : undefined };
}

async function main() {
  let cursor: string | undefined;
  let allTweets: { id: string; text: string; timestamp: string }[] = [];

  for (let page = 0; page < 5; page++) {
    const { tweets, nextCursor } = await scrapeListPage(cursor);
    allTweets.push(...tweets);
    console.log(`Page ${page + 1}: +${tweets.length} tweets (${allTweets.length} total)`);
    if (!nextCursor) break;
    cursor = nextCursor;
    await new Promise(r => setTimeout(r, 1000)); // polite delay
  }

  console.log(JSON.stringify(allTweets, null, 2));
}

main();

Empirical Findings (Apr 2026)

Instance Selection

nitter.net itself is often up but headless Playwright returns "Oh noes!" (rate-limited/blocked). Always use headless: false or channel: 'chrome'. Working instances confirmed Apr 15 2026:

InstanceStatus
nitter.tiekoetter.com✅ reliable, used successfully
nitter.privacyredirect.com⚠️ TLS timeout
nitter.catsarch.com✅ listed as up
xcancel.com✅ listed as up
nitter.net✅ up but may block headless

Check live status at: https://status.d420.de/

Build a priority list and auto-fallback. Accept an instance as valid only after .timeline-item is found in DOM, not just by page title:

ts
const ok = await page.waitForSelector('.timeline-item', { timeout: 10000 })
  .then(() => true).catch(() => false);
// Don't trust page.title() — error pages can spoof it
Headless Always Fails

Nitter instances actively detect headless Chromium and return a blank/error page. Always use headless: false (or channel: 'chrome' which implies headed). The --disable-blink-features=AutomationControlled arg and navigator.webdriver override are also necessary:

ts
const browser = await chromium.launch({
  headless: false, // REQUIRED — headless gets blocked
  args: ['--disable-blink-features=AutomationControlled'],
});
await context.addInitScript(() => {
  Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
});
Pagination: Cursor URL Construction

The div.show-more a href is a relative URL like ?cursor=DAA.... Do NOT construct baseUrl + href naively — the correct form is:

ts
// ✅ correct
const nextUrl = `${baseUrl}/${handle}${nextHref}`; // nextHref starts with "?"

// ❌ wrong — this double-encodes or drops the path
const nextUrl = new URL(nextHref, baseUrl).href;

Verify by logging the constructed URL before page.goto().

Timestamp Parsing

The .tweet-date a element has two useful attributes:

  • title — full absolute date: "Apr 14, 2026 · 5:47 PM UTC" — always use this for cutoff comparisons
  • textContent — relative display: "19h" or "Apr 14" — unreliable for parsing

The · separator is a Unicode middle dot (\u00B7), not ASCII. Split on it:

ts
const datePart = title.split('·')[0].trim(); // "Apr 14, 2026 "
const date = new Date(datePart); // reliable

Do not try to parse "19h" — if title is missing, skip or don't cutoff on that tweet.

Show full SKILL.md (248 more words)Show less
Pinned Posts

The first .timeline-item is often a pinned post that can be years old, causing a false early cutoff. Skip it:

ts
const isPinned = item.classList.contains('pinned') ||
  !!item.querySelector('.pinned-icon, .icon-pin');
if (isPinned) continue;

Also: check the oldest non-pinned tweet's date for the cutoff, not just the oldest tweet.

Avatar Scraping (No Auth)

The CSS selector reference lists .tweet-header a.tweet-avatar img.avatar[src] — use this instead of unavatar.io to get avatars directly from Nitter without a third-party service:

ts
const avatarSrc = $el.find('.tweet-header a.tweet-avatar img.avatar').attr('src');
// Returns a relative path like /pic/pbs.twimg.com%2F...
// Decode it:
const avatarUrl = avatarSrc
  ? 'https://pbs.twimg.com/' + decodeURIComponent(avatarSrc.replace('/pic/', '').replace('pbs.twimg.com%2F', ''))
  : undefined;

Or just store the Nitter-proxied URL: ${instance}${avatarSrc} (will break if instance changes).

Avoid unavatar.io/twitter/<handle> — it 301-redirects to /x/<handle> and has a low anonymous daily rate limit (hits quickly when backfilling many users). Use it only as a fallback when Nitter avatar is unavailable.

Tweet Author URL Points to Original on Retweets

On a retweet, a.tweet-link href points to the original author's tweet (e.g. /originalAuthor/status/123), not /@swyx/status/.... This is what you want for linking to the source. Extract the author from the href:

ts
const authorMatch = href.match(/^\/([^/]+)\/status/);
const author = authorMatch?.[1]; // original author's handle

Dependencies

json
{
  "axios": "^1.7.2",
  "cheerio": "^1.0.0",
  "playwright": "^1.58.2"
}

Install Playwright browsers once: npx playwright install chrome


CSS Selector Reference

DataSelector
Tweet container.timeline .timeline-item (filter: has .tweet-body)
Tweet link / IDa.tweet-link[href] → extract /status/(\d+)/
Timestamp.tweet-date a[title]
Tweet text.tweet-content.media-body
Author username.tweet-header a.username[title]
Author display name.tweet-header a.fullname[title]
Avatar.tweet-header a.tweet-avatar img.avatar[src]
Images.attachments .attachment.image img[src]
Videos.attachments .gallery-video img[src] (poster)
Link card.card a.card-container[href]
Likes.tweet-stat span.icon-heart → sibling text
Retweets.tweet-stat span.icon-retweet → sibling text
Replies.tweet-stat span.icon-comment → sibling text
Quote tweets.tweet-stat span.icon-quote → sibling text
Retweet banner.retweet-header (non-empty = is a retweet)
Quoted tweet block.quote
Quoted text.quote .quote-text
Next page cursordiv.show-more a[href] → extract ?cursor=

© swyxio, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in twitter-x-scraping of swyxio/skills.

Open the folder on GitHubat commit 038ef34

Compare with similar skills

Twitter X Scraping next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Twitter X Scraping compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Twitter X Scraping this skillswyxio/skills176—~3.5kAutomated safety check: PassMIT
Python Executorcortega26/chile-hub1132 repos~1.5kAutomated safety check: PassMIT
Using Webctloaustegard/claude-skills150—~1.4kAutomated safety check: PassMIT
Extractactionbook/actionbook1.6k2 repos~3.4kAutomated safety check: PassApache-2.0
Playwright Bowserdisler/bowser265—~1.1kAutomated safety check: NotesNone
Anti Detect Browserantibrow/anti-detect-browser-skills17—~9.8kAutomated safety check: WarnMIT

Similar skills

  • Python Executor

    cortega26/chile-hub

    Execute Python code in a safe sandboxed environment via [inference.sh](https://inference.sh).

    113 GitHub starsUsed in 2 repos~1.5k tokens
    Data & AnalyticsAuto-check passed
  • Using Webctl

    oaustegard/claude-skills

    Browser automation via webctl CLI in Claude.ai containers with authenticated proxy support.

    150 GitHub stars~1.4k tokensUpdated yesterday
    Productivity & AutomationAuto-check passed
  • Extract

    actionbook/actionbook

    Extract structured data from websites and produce an executable Playwright script plus extracted data.

    1.6k GitHub starsUsed in 2 repos~3.4k tokens
    Sales & SupportAuto-check passed
  • Playwright Bowser

    disler/bowser

    Headless browser automation using Playwright CLI. An agent skill from disler/bowser.

    265 GitHub stars~1.1k tokensUpdated 7 mo ago
    Productivity & AutomationAuto-check: notes
  • Anti Detect Browser

    antibrow/anti-detect-browser-skills

    Drive Chromium from standard Playwright APIs with a real-device fingerprint applied in the kernel, one persistent isolated profile per identity, and a per-profile proxy whose exit IP sets timezone…

    17 GitHub stars~9.8k tokensUpdated 1 mo ago
    Testing & QAAuto-check: warnings
  • Cloudflare Browser Rendering

    secondsky/claude-skills

    Cloudflare Browser Rendering with Puppeteer/Playwright. An agent skill from secondsky/claude-skills.

    227 GitHub stars~4k tokensUpdated 13 days ago
    Testing & QAAuto-check passed

More from swyxio/skills

All 89 skills in this repo
  • Programmatic Agents

    swyxio/skills

    Run a selected coding-agent CLI programmatically, with latency, error, usage, cost, and trace logging.

    176 GitHub stars~2.2k tokensUpdated today
    Auto-check passed
  • Design, implement, audit, or refresh protected username and handle namespaces for public products.

    176 GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • New Mac Setup

    swyxio/skills

    Fully automated new Mac setup for fullstack web developers and AI engineers.

    176 GitHub stars~4.3k tokensUpdated today
    Auto-check passed
  • Youtube API

    swyxio/skills

    Manage YouTube videos programmatically via the YouTube Data API v3 — upload video files, upload custom thumbnails, update video metadata (titles, descriptions, tags), and query video/channel info…

    176 GitHub stars~2.2k tokensUpdated today
    Auto-check passed
  • Batch YouTube Studio upload workflow for videos sourced from Airtable, Google Drive, Loom, YouTube, or local files.

    176 GitHub stars~1.5k tokensUpdated today
    Auto-check: warnings
  • Reconstruct and visually analyze paired agent, game, or policy trajectories to determine whether changed actions produced their intended effects.

    176 GitHub stars~1.8k tokensUpdated today
    Auto-check passed

Questions about Twitter X Scraping

What does Twitter X Scraping do?

A skill your agent uses when scraping public Twitter/X timelines or lists through Nitter-style mirrors with axios and Playwright fallback, including anti-bot challenge handling and pagination limits. Twitter X Scraping is an agent skill from swyxio/skills. Use when scraping public Twitter/X timelines or lists through Nitter-style mirrors with axios and Playwright fallback, including anti-bot challenge handling and pagination limits.

When should I use Twitter X Scraping?

Twitter X Scraping fits situations like: scraping public Twitter/X timelines; lists through Nitter-style mirrors with axios and Playwright fallback; including anti-bot challenge handling and pagination limits.

How do I install Twitter X Scraping in Claude Code?

Run `npx skills add swyxio/skills --skill twitter-x-scraping -a claude-code`. Or copy the skill folder (twitter-x-scraping in swyxio/skills) into .claude/skills/twitter-x-scraping in your project. Claude Code loads it when a task matches its description.

How do I install Twitter X Scraping in Codex?

Run `npx skills add swyxio/skills --skill twitter-x-scraping -a codex`. Or copy the skill folder (twitter-x-scraping in swyxio/skills) into .agents/skills/twitter-x-scraping in your project. Codex loads it when a task matches its description.

Can I use Twitter X Scraping in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add swyxio/skills --skill twitter-x-scraping -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/twitter-x-scraping, .gemini/skills/twitter-x-scraping, .github/skills/twitter-x-scraping and .opencode/skills/twitter-x-scraping in your project.

What does Twitter X Scraping need to run?

Going by SKILL.md and its folder, Twitter X Scraping needs the command-line tools its instructions call (npx). Our summary lists: Node.js.

Does Twitter X Scraping access the network?

SKILL.md names 3 domains. In commands or code: nitter.net and pbs.twimg.com; the agent is likely to contact these when it follows the instructions. As links in the text: status.d420.de. This is read from the text; nothing was executed.

Is Twitter X Scraping safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Twitter X Scraping use?

Twitter X Scraping is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Twitter X Scraping use?

About 3.5k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Twitter X Scraping?

Skills that share tags, products or a category with Twitter X Scraping: Python Executor (cortega26/chile-hub, 113 stars), Using Webctl (oaustegard/claude-skills, 150 stars), Extract (actionbook/actionbook, 1.6k stars) and Playwright Bowser (disler/bowser, 265 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Twitter X Scraping?

swyxio (a GitHub user) maintains it in swyxio/skills, which has 176 GitHub stars. The repository holds 89 skills in this directory. The repository was last updated on October 5, 2026.

Source: swyxio/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.