Skip to content

masa-finance/twitter-scraper

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

379 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Twitter Scraper

Go Reference

Production-focused scraper for X web endpoints.

This fork is maintained around the endpoint surface the codebase actually implements and that we actively test. It is intended for authenticated scraping with real browser cookies.

Installation

go get -u github.com/imperatrona/twitter-scraper

What This Supports

The production-maintained surface documented in this README is:

  • Authentication via SetCookies or SetAuthToken
  • GetTweet
  • GetTweetReplies
  • GetTweetRetweeters
  • GetTweets
  • GetTweetsAndReplies
  • FetchTweets
  • FetchTweetsAndReplies
  • FetchTweetsByUserID
  • FetchTweetsAndRepliesByUserID
  • GetHomeTweets
  • FetchHomeTweets
  • SearchTweets
  • FetchSearchTweets
  • SearchProfiles
  • FetchSearchProfiles
  • GetProfile
  • GetProfileByID
  • GetUserIDByScreenName
  • GetTrends
  • GetCookies
  • Logout
  • Proxy support via SetProxy
  • User-Agent overrides via SetUserAgent

The older README documented a much larger feature set; unsupported or unmaintained sections have been removed here so production docs match the code we actually keep current.

Quick Start

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"os"

	twitterscraper "github.com/imperatrona/twitter-scraper"
)

func main() {
	var cookies []*http.Cookie

	f, err := os.Open("cookies.json")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	if err := json.NewDecoder(f).Decode(&cookies); err != nil {
		panic(err)
	}

	scraper := twitterscraper.New()
	scraper.SetCookies(cookies)

	if !scraper.IsLoggedIn() {
		panic("missing auth cookies")
	}

	for tweet := range scraper.SearchTweets(context.Background(), "subnet signal", 20) {
		if tweet.Error != nil {
			panic(tweet.Error)
		}
		fmt.Println(tweet.ID, tweet.Text)
	}
}

Authentication

Most useful endpoints in this library require authentication.

The recommended approach is to load browser cookies containing at least:

  • auth_token
  • ct0

Using cookies

var cookies []*http.Cookie

f, err := os.Open("cookies.json")
if err != nil {
	panic(err)
}
defer f.Close()

if err := json.NewDecoder(f).Decode(&cookies); err != nil {
	panic(err)
}

scraper.SetCookies(cookies)
if !scraper.IsLoggedIn() {
	panic("invalid cookies")
}

Using AuthToken

scraper.SetAuthToken(twitterscraper.AuthToken{
	Token:     "auth_token",
	CSRFToken: "ct0",
})

if !scraper.IsLoggedIn() {
	panic("invalid auth token")
}

Saving cookies

cookies := scraper.GetCookies()

data, err := json.Marshal(cookies)
if err != nil {
	panic(err)
}

if err := os.WriteFile("cookies.json", data, 0o600); err != nil {
	panic(err)
}

Logging out

if err := scraper.Logout(); err != nil {
	panic(err)
}

Channel-Based Methods

Some methods stream results over a channel and paginate internally. Always check Error before using the item.

for tweet := range scraper.GetTweets(context.Background(), "x", 50) {
	if tweet.Error != nil {
		panic(tweet.Error)
	}
	fmt.Println(tweet.Text)
}

These channel helpers use the same underlying endpoints and rate limits as their corresponding Fetch* methods.

Supported Methods

Get a tweet

tweet, err := scraper.GetTweet("1328684389388185600")

Get tweet replies

replies, cursors, err := scraper.GetTweetReplies("1328684389388185600", "")

GetTweetReplies can return multiple cursors, one per thread branch.

Get tweet retweeters

profiles, cursor, err := scraper.GetTweetRetweeters("1328684389388185600", 20, "")

Get user tweets

for tweet := range scraper.GetTweets(context.Background(), "taylorswift13", 50) {
	if tweet.Error != nil {
		panic(tweet.Error)
	}
	fmt.Println(tweet.Text)
}

Fetch user tweets

tweets, cursor, err := scraper.FetchTweets("taylorswift13", 20, "")

Get user tweets and replies

for tweet := range scraper.GetTweetsAndReplies(context.Background(), "taylorswift13", 50) {
	if tweet.Error != nil {
		panic(tweet.Error)
	}
	fmt.Println(tweet.Text)
}

Fetch tweets by numeric user ID

tweets, cursor, err := scraper.FetchTweetsByUserID("783214", 20, "")

Fetch tweets and replies by numeric user ID

tweets, cursor, err := scraper.FetchTweetsAndRepliesByUserID("783214", 20, "")

Get home timeline

Requires authentication.

for tweet := range scraper.GetHomeTweets(context.Background(), 50) {
	if tweet.Error != nil {
		panic(tweet.Error)
	}
	fmt.Println(tweet.Text)
}

Fetch home timeline page

Requires authentication.

tweets, cursor, err := scraper.FetchHomeTweets(20, "")

Search tweets

Requires authentication.

for tweet := range scraper.SearchTweets(context.Background(), "twitter scraper -filter:retweets", 50) {
	if tweet.Error != nil {
		panic(tweet.Error)
	}
	fmt.Println(tweet.Text)
}

Use SetSearchMode to switch modes. Supported modes are:

  • SearchTop
  • SearchLatest
  • SearchPhotos
  • SearchVideos
  • SearchUsers
scraper.SetSearchMode(twitterscraper.SearchLatest)

Fetch tweet search page

tweets, cursor, err := scraper.FetchSearchTweets("subnet signal", 20, "")

Search profiles

Requires authentication.

for profile := range scraper.SearchProfiles(context.Background(), "Twitter", 20) {
	if profile.Error != nil {
		panic(profile.Error)
	}
	fmt.Println(profile.Username, profile.Name)
}

Fetch profile search page

profiles, cursor, err := scraper.FetchSearchProfiles("Twitter", 20, "")

Get profile by username

profile, err := scraper.GetProfile("taylorswift13")

Get profile by numeric user ID

profile, err := scraper.GetProfileByID("783214")

Resolve numeric user ID from screen name

userID, err := scraper.GetUserIDByScreenName("twitter")

Get trends

trends, err := scraper.GetTrends()

Connection Settings

User-Agent

scraper.SetUserAgent("Mozilla/5.0 ...")
agent := scraper.GetUserAgent()
_ = agent

HTTP proxy

err := scraper.SetProxy("http://localhost:3128")

SOCKS5 proxy

err := scraper.SetProxy("socks5://localhost:1080")

SOCKS5 with auth is also supported:

err := scraper.SetProxy("socks5://user:pass@localhost:1080")

Operational Notes

  • X rotates GraphQL query IDs and feature payloads over time. This repo tracks the web client, not the public API.
  • Authenticated GraphQL requests depend on x-client-transaction-id; the library generates that header automatically.
  • Rate limits change without notice. Add pacing, retries, and account rotation in production.
  • Prefer cookies from a real logged-in browser session over password automation.

Testing

Authenticated tests need valid session credentials. Keep secrets out of git.

In practice, the easiest path is to provide a local cookies.json with a current session before running:

go test ./...

About

Scrape the Twitter frontend API without authentication with Golang.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Go 100.0%