goat-x-pro
v0.1.1
Published
X Pro (TweetDeck) scraper client for Bun
Maintainers
Readme
goat-x-pro
A lightweight X (Twitter) scraper using X Pro (TweetDeck) GraphQL endpoints.
Built with Bun and TypeScript. Uses native fetch - no browser automation required.
Installation
# npm
npm install goat-x-pro
# bun
bun add goat-x-proQuick Start
import { XProClient } from 'goat-x-pro';
const client = new XProClient({
cookiesPath: './cookies.json',
});
await client.login();
console.log(`Logged in as @${client.user?.username}`);
// Search tweets
const tweets = await client.search('SpaceX', { count: 50 });
// Get list timeline
const listTweets = await client.getListTimeline('1697015778342785371', { count: 50 });Authentication Setup
- Log in to https://x.com in your browser
- Open DevTools (F12) → Application → Cookies → x.com
- Copy
auth_tokenandct0values - Create
cookies.json:
[
{
"name": "auth_token",
"value": "YOUR_AUTH_TOKEN_HERE",
"domain": ".x.com",
"path": "/"
},
{
"name": "ct0",
"value": "YOUR_CT0_TOKEN_HERE",
"domain": ".x.com",
"path": "/"
}
]API Reference
XProClient
Constructor
import { XProClient } from 'goat-x-pro';
const client = new XProClient({
// Path to cookies.json file
cookiesPath?: string;
// Or provide cookies directly
cookies?: Cookie[];
// Proxy in format: host:port:username:password
proxy?: string;
// Enable debug logging
debug?: boolean;
});Methods
login(): Promise<void>
Authenticate and verify session. Must be called before other methods.
await client.login();search(query: string, options?: SearchOptions): Promise<Tweet[]>
Search tweets with automatic pagination.
const tweets = await client.search('$BTC', {
count: 100, // Total tweets to fetch (auto-paginates)
product: 'Latest', // 'Top' | 'Latest' | 'People' | 'Photos' | 'Videos'
});searchPage(query: string, options?: SearchOptions): Promise<TimelineResponse>
Get a single page of search results with cursor for manual pagination.
const { tweets, nextCursor } = await client.searchPage('query', {
count: 20,
cursor: previousCursor,
});getListTimeline(listId: string, options?: ListTimelineOptions): Promise<Tweet[]>
Get tweets from a list with automatic pagination.
const tweets = await client.getListTimeline('1697015778342785371', {
count: 50,
});getListTimelinePage(listId: string, options?: ListTimelineOptions): Promise<TimelineResponse>
Get a single page of list tweets with cursor.
const { tweets, nextCursor } = await client.getListTimelinePage('1697015778342785371', {
count: 20,
cursor: previousCursor,
});isLoggedIn(): boolean
Check if client is authenticated.
user: Profile | null
The authenticated user's profile (available after login).
Types
Tweet
interface Tweet {
id: string;
text: string;
username: string;
name: string;
userId: string;
createdAt: string;
timestamp: number;
// Metrics
likes: number;
retweets: number;
replies: number;
quotes: number;
bookmarks: number;
views: number;
// Engagement state
isLiked: boolean;
isRetweeted: boolean;
isBookmarked: boolean;
// Context
conversationId?: string;
inReplyToStatusId?: string;
inReplyToUserId?: string;
inReplyToUsername?: string;
isReply: boolean;
isRetweet: boolean;
isQuoted: boolean;
// Attachments
urls: string[];
hashtags: string[];
mentions: Mention[];
photos: Photo[];
videos: Video[];
// Related tweets
quotedTweet?: Tweet;
retweetedTweet?: Tweet;
// Metadata
source?: string;
lang?: string;
sensitiveContent: boolean;
}Profile
interface Profile {
id: string;
username: string;
name: string;
description?: string;
location?: string;
url?: string;
avatarUrl: string;
avatarShape: 'Circle' | 'Square';
bannerUrl?: string;
createdAt?: string;
isProtected: boolean;
isVerified: boolean;
isBlueVerified: boolean;
// Stats
followersCount: number;
followingCount: number;
tweetsCount: number;
likesCount: number;
listedCount: number;
mediaCount: number;
// Relationship state
following?: boolean;
followedBy?: boolean;
blocking?: boolean;
muting?: boolean;
canDm?: boolean;
pinnedTweetIds: string[];
}Mention
interface Mention {
id: string;
username: string;
name?: string;
}Photo
interface Photo {
id: string;
url: string;
altText?: string;
}Video
interface Video {
id: string;
url?: string;
preview: string;
variants?: VideoVariant[];
}
interface VideoVariant {
bitrate?: number;
contentType: string;
url: string;
}SearchOptions
interface SearchOptions {
count?: number;
product?: 'Top' | 'Latest' | 'People' | 'Photos' | 'Videos';
cursor?: string;
}ListTimelineOptions
interface ListTimelineOptions {
count?: number;
includePromotedContent?: boolean;
cursor?: string;
}TimelineResponse
interface TimelineResponse {
tweets: Tweet[];
nextCursor?: string;
previousCursor?: string;
}Cookie
interface Cookie {
name: string;
value: string;
domain: string;
path: string;
expires?: number;
httpOnly?: boolean;
secure?: boolean;
sameSite?: string;
}Proxy Support
Use a proxy by passing the proxy option in format host:port:username:password:
const client = new XProClient({
cookiesPath: './cookies.json',
proxy: '208.195.166.215:65095:username:password',
});Or as a full URL:
proxy: 'http://username:password@host:port'Manual Pagination Example
import { XProClient } from 'goat-x-pro';
const client = new XProClient({ cookiesPath: './cookies.json' });
await client.login();
let cursor: string | undefined;
const allTweets: Tweet[] = [];
while (allTweets.length < 200) {
const { tweets, nextCursor } = await client.searchPage('crypto', {
count: 20,
cursor,
});
allTweets.push(...tweets);
if (!nextCursor || tweets.length === 0) break;
cursor = nextCursor;
}
console.log(`Fetched ${allTweets.length} tweets`);Debug Logging
Enable debug mode to see detailed request/response logs:
import { XProClient, setLogLevel } from 'goat-x-pro';
setLogLevel('debug');
const client = new XProClient({
cookiesPath: './cookies.json',
debug: true,
});Exports
import {
// Main client
XProClient,
// Types
Tweet,
Profile,
Cookie,
Mention,
Photo,
Video,
VideoVariant,
SearchOptions,
ListTimelineOptions,
TimelineResponse,
XProClientConfig,
// Parsers (for custom parsing)
parseTweet,
parseTweets,
parseUser,
parseTimeline,
// Constants
BEARER_TOKEN,
BASE_HEADERS,
GRAPHQL_FEATURES,
ENDPOINTS,
// Logger utilities
logger,
setLogLevel,
createLogger,
} from 'goat-x-pro';Notes
- Uses X Pro (TweetDeck) GraphQL endpoints
- Requires valid X session cookies (
auth_tokenandct0) - Respects rate limits automatically
- Keep your cookies secure - never commit them to version control
License
MIT
