npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

birdnode

v1.9.5

Published

Cross-platform CLI for X (Twitter) — reads Chrome cookies and calls X's GraphQL APIs directly. No API key needed.

Downloads

1,975

Readme

birdnode

Node.js CLI for X (Twitter) — reads Chrome cookies and directly calls X's internal GraphQL APIs. Supports macOS / Linux / Windows.

How it Works

  1. Reads Chrome Cookies: Extracts ct0 and auth_token using OS-specific decryption methods (see below).
  2. Dynamic QueryId Discovery: Automatically fetches and parses X.com's JS Bundles to dynamically find the latest GraphQL QueryIds (preventing hardcoded IDs from breaking).
  3. Calls X's GraphQL APIs: Uses the extracted cookies and QueryIds to send POST requests directly to X's internal GraphQL endpoints.

Cookie Decryption Methods

| Platform | Cookie Path | Algorithm | Key Source | |------|------------|---------|---------| | macOS | ~/Library/.../Chrome/Default/Cookies | AES-128-CBC | macOS Keychain (Chrome Safe Storage) | | Linux | ~/.config/google-chrome/Default/Cookies | AES-128-CBC | Hardcoded "peanuts", or GNOME Keyring / KWallet | | Windows | %LOCALAPPDATA%\...\Chrome\User Data\Default\Cookies | AES-256-GCM | Windows DPAPI decrypts Master Key in Local State |

Note: For Chrome 127+, X prepends a 32-byte SHA256 domain hash to the decrypted data, which the tool automatically detects and strips.

Installation & Usage

You can run it directly via npx without installing globally:

npx birdnode help

Or install it globally:

npm install -g birdnode

Requires Node.js 18+ (uses the built-in fetch).

Commands

# Show help
birdnode help

# View currently logged-in account
birdnode whoami
birdnode whoami --json

# Search tweets
birdnode search "bitcoin" -n 20
birdnode search "solana memecoin" -n 5 --product Top
birdnode search "bitcoin" -n 10 --json

# Deep Token Analysis (DexScreener + Official + Global Tweets)
birdnode analyze 0x514910771af9ca656af840dff83e8264ecf986ca
birdnode analyze 0x5149... --json

# View user profile
birdnode user elonmusk
birdnode user @vitalikbuterin
birdnode user elonmusk --json

# Check who is mentioning/talking AT a user
birdnode mentions elonmusk
birdnode mentions @vitalikbuterin -n 50
birdnode mentions elonmusk --json

# Check credentials status
birdnode check

# Post a tweet
birdnode tweet "Hello World 🚀"

# Reply to a tweet
birdnode reply 1234567890987654321 "This is a reply to your post!"

# Fetch main tweet only (ignores comments)
birdnode read 1234567890987654321
# You can also pass full X/Twitter URLs instead of raw IDs!
birdnode read https://x.com/elonmusk/status/1234 --json

# Fetch ONLY the replies/comments left by others
birdnode replies 1234567890987654321
birdnode replies 1234567890987654321 --json

# Fetch the author's self-thread conversation
birdnode thread 1234567890987654321
birdnode thread 1234567890987654321 --json

# Get followers list
birdnode followers <user_id> -n 50

# Get following list
birdnode following <user_id> -n 50

Options

| Option | Description | |------|------| | -n <count> | Number of results to return (default: 20) | | --product <type> | Search criteria: Latest | Top (default: Latest) | | --chrome-profile <name>| Specific Chrome Profile to extract cookies from (default: auto-detect) | | --auth-token <token> | Manually override the auth_token cookie | | --ct0 <token> | Manually override the ct0 cookie | | --json | Return raw JSON output |

Environment Variables

You can completely bypass the local Chrome database lookup by passing credentials via environment variables:

export CT0="your_ct0_token"
export AUTH_TOKEN="your_auth_token"
birdnode search "bitcoin"

Credential Priority

  1. CLI flags (--ct0 and --auth-token)
  2. Environment variables (CT0 / TWITTER_CT0, AUTH_TOKEN / TWITTER_AUTH_TOKEN)
  3. Chromium / Chrome cookie database fallback (requires permission to read)

Notes

macOS

  • Chrome must be logged into x.com.
  • The first time it runs, macOS may prompt for Keychain Access. Click "Allow" or "Always Allow".
  • If permission is denied, open "Keychain Access" and manually grant access to "Chrome Safe Storage".

Linux

  • Supports both Google Chrome and Chromium.
  • If GNOME Keyring is installed and unlocked, its password will be prioritized.
  • On headless/server setups without a desktop keyring, Chrome automatically falls back to an internal hardcoded password ("peanuts"), which is fully supported.
  • Snap Chromium path is also supported: ~/snap/chromium/current/.config/chromium.

Windows

  • Chrome 80+ uses Windows DPAPI to protect an AES-256 master key (stored in the Local State JSON file).
  • You must run the command as the same Windows user that runs Chrome (DPAPI is tied to the active Windows user account).
  • A temporary PowerShell process is spawned (ProtectedData.Unprotect) to decrypt the key, requiring basic PowerShell execution permissions.
  • Older Chrome (< 80) cookies encrypted completely via DPAPI are also seamlessly supported.

General

  • X's GraphQL QueryIds change frequently. birdnode automatically parses modern X JS bundles at runtime to discover the latest queryId identifiers.
  • Please respect X's Terms of Service and avoid aggressive or severely rate-limiting requests.

Architecture

birdnode/
├── src/
│   ├── index.js              # CLI entry point, argument parsing and printing
│   ├── token-analyzer.js     # Complex multi-step analysis orchestration
│   ├── query-id-resolver.js  # Dynamic GraphQL query engine and extraction
│   ├── cookie-extractor.js   # Cross-platform cookie decrypter (macOS/Linux/Win)
│   └── twitter-api.js        # X GraphQL and REST API logic
├── test/
│   └── test-new-api.js       # Live API automated testing scripts 
└── package.json

Advanced Library Usage (Node.js API)

In addition to the CLI commands, you can seamlessly import birdnode directly as an NPM dependency into your bots/projects. It exposes powerful native capabilities that bypass normal GraphQL blocks:

const { getXCredentials } = require('birdnode/src/cookie-extractor');
const { postTweet, getTweetThread } = require('birdnode/src/twitter-api');

(async () => {
   const creds = await getXCredentials();
   
   // 1. Post a new tweet natively
   const newTweet = await postTweet({
      text: 'Automated post testing!',
      ct0: creds.ct0,
      authToken: creds.authToken
   });
   
   // 2. Fetch an entire Thread (Main Tweet + Thread + All user Replies)
   const threadData = await getTweetThread({
      tweetId: '1234567890987654321', // Any active tweet ID
      ct0: creds.ct0,
      authToken: creds.authToken
   });
   console.log(threadData.thread);
})();