xclient

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 6, 2026 License: MIT Imports: 30 Imported by: 0

Documentation

Overview

Package xclient is an authenticated client for x.com's internal GraphQL/REST API. It signs every request with a freshly generated x-client-transaction-id (see pkg/transaction) and a complete browser-like header set, which is what keeps cookie sessions alive instead of getting them flagged and expired.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BadgeCount

type BadgeCount struct {
	Notifications int `json:"notifications"`
	DM            int `json:"dm"`
	XChat         int `json:"xchat"`
	Total         int `json:"total"`
}

BadgeCount holds the unread counters x.com shows on its nav badges.

type BookmarkFolder

type BookmarkFolder struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

BookmarkFolder is a named bookmark collection.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to x.com on behalf of a single account.

func New

func New(acc *account.Account, opts ...Option) (*Client, error)

New builds a Client for an account.

func (*Client) Account

func (c *Client) Account() *account.Account

Account returns the account this client serves.

func (*Client) AddListMember

func (c *Client) AddListMember(ctx context.Context, listID, userID string) error

AddListMember adds a user (by numeric id) to a List the account owns.

func (*Client) Article

func (c *Client) Article(ctx context.Context, tweetID string, markdown bool) (*models.Tweet, error)

Article fetches a single tweet by id via TweetResultByRestId and populates the X Article fields when the tweet is a long-form article. markdown renders the article body as markdown instead of plain text. Non-article tweets are returned with empty article fields.

func (*Client) Badges

func (c *Client) Badges(ctx context.Context) (*BadgeCount, error)

Badges returns the account's unread counts (notifications, DMs, XChat) via the v2 badge_count endpoint.

func (*Client) Block

func (c *Client) Block(ctx context.Context, screenName string) error

func (*Client) Bookmark

func (c *Client) Bookmark(ctx context.Context, tweetID string) error

Bookmark saves a tweet.

func (*Client) BookmarkFolderTweets

func (c *Client) BookmarkFolderTweets(ctx context.Context, folderID string, count int, cursor string) (*models.Page, error)

BookmarkFolderTweets returns the tweets saved in a bookmark folder.

func (*Client) BookmarkFolders

func (c *Client) BookmarkFolders(ctx context.Context) ([]BookmarkFolder, error)

BookmarkFolders lists the account's bookmark folders.

func (*Client) BookmarkToFolder

func (c *Client) BookmarkToFolder(ctx context.Context, tweetID, folderID string) error

BookmarkToFolder bookmarks a tweet into a specific folder.

func (*Client) Bookmarks

func (c *Client) Bookmarks(ctx context.Context, count int, cursor string) (*models.Page, error)

Bookmarks fetches the authenticated user's bookmarked tweets.

func (*Client) CommunityInfo

func (c *Client) CommunityInfo(ctx context.Context, communityID string) (map[string]any, error)

CommunityInfo returns metadata about a Community (name, description, member count, join policy, role) by its numeric id.

func (*Client) CommunityTweets

func (c *Client) CommunityTweets(ctx context.Context, communityID string, count int, cursor string, latest bool) (*models.Page, error)

CommunityTweets returns the timeline of posts in a Community. When latest is true the timeline is ranked by recency, otherwise by relevance (the x.com web defaults).

func (*Client) CreateBookmarkFolder

func (c *Client) CreateBookmarkFolder(ctx context.Context, name string) (*BookmarkFolder, error)

CreateBookmarkFolder creates a new bookmark folder and returns it.

func (*Client) CreateCommunity

func (c *Client) CreateCommunity(ctx context.Context, name string) (map[string]any, error)

CreateCommunity creates a new Community with the given name and returns its id and name. NOTE: creating a Community is a permanent, public action and is not undoable via this client. x.com also gates creation by account standing: ineligible accounts get a CommunityCreateActionUnavailable result, surfaced here as an error (verified live — a fresh burner cannot create Communities, so no Community is actually created in that case).

func (*Client) CreateDraft

func (c *Client) CreateDraft(ctx context.Context, text string, mediaIDs []string) (string, error)

CreateDraft saves a draft tweet and returns its id.

func (*Client) CreateList

func (c *Client) CreateList(ctx context.Context, name, description string, private bool) (map[string]any, error)

CreateList creates a List owned by the authenticated account and returns its id and name.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, tweetID string) error

Delete removes one of the authenticated user's tweets.

func (*Client) DeleteBookmarkFolder

func (c *Client) DeleteBookmarkFolder(ctx context.Context, folderID string) error

DeleteBookmarkFolder deletes a bookmark folder by id.

func (*Client) DeleteDraft

func (c *Client) DeleteDraft(ctx context.Context, draftID string) error

DeleteDraft removes a draft tweet by id.

func (*Client) DeleteList

func (c *Client) DeleteList(ctx context.Context, listID string) error

DeleteList deletes a List owned by the authenticated account.

func (*Client) DeleteScheduledTweet

func (c *Client) DeleteScheduledTweet(ctx context.Context, scheduledTweetID string) error

DeleteScheduledTweet removes a pending scheduled tweet by id.

func (*Client) DirectMessages

func (c *Client) DirectMessages(ctx context.Context, count int) ([]DirectMessage, error)

DirectMessages lists recent DMs (incoming and outgoing, including message requests) via the rich inbox_initial_state endpoint, newest first. The older events/list.json endpoint omits some conversations, so this one is used.

func (*Client) DownloadMedia

func (c *Client) DownloadMedia(ctx context.Context, rawURL string) ([]byte, string, error)

DownloadMedia fetches the bytes of an auth-gated media URL (e.g. a DM attachment on ton.twitter.com / video.twimg.com) using the account's cookies, returning the body and its Content-Type.

func (*Client) Drafts

func (c *Client) Drafts(ctx context.Context) ([]Draft, error)

Drafts lists the account's saved draft tweets.

func (*Client) Favoriters

func (c *Client) Favoriters(ctx context.Context, tweetID string, count int, cursor string) (*models.UserPage, error)

Favoriters returns the accounts that liked a tweet.

func (*Client) Follow

func (c *Client) Follow(ctx context.Context, screenName string) error

Follow / Unfollow / Mute / Unmute / Block / Unblock act on another user by @handle via the legacy v1.1 endpoints, which accept screen_name directly.

func (*Client) FollowTopic

func (c *Client) FollowTopic(ctx context.Context, topicID string) error

FollowTopic / UnfollowTopic manage the account's followed Topics.

func (*Client) Followers

func (c *Client) Followers(ctx context.Context, userID string, count int, cursor string) (*models.UserPage, error)

Followers fetches a user's followers by numeric user id.

func (*Client) FollowersByScreenName

func (c *Client) FollowersByScreenName(ctx context.Context, screenName string, count int, cursor string) (*models.UserPage, error)

FollowersByScreenName / FollowingByScreenName resolve a @handle first.

func (*Client) Following

func (c *Client) Following(ctx context.Context, userID string, count int, cursor string) (*models.UserPage, error)

Following fetches the accounts a user follows by numeric user id.

func (*Client) FollowingByScreenName

func (c *Client) FollowingByScreenName(ctx context.Context, screenName string, count int, cursor string) (*models.UserPage, error)

func (*Client) GrokAsk

func (c *Client) GrokAsk(ctx context.Context, prompt string) (string, error)

GrokAsk sends a single prompt to Grok and returns the assembled reply. It creates a fresh conversation, posts the prompt to the streaming /2/grok/add_response endpoint, and concatenates the streamed answer tokens.

func (*Client) GrokImage

func (c *Client) GrokImage(ctx context.Context, prompt string) ([]string, error)

GrokImage asks Grok to generate image(s) and returns their attachment URLs. With toolOverrides.imageGen the add_response stream itself carries the generated image cards (imageAttachment.mediaId), so the ids are read straight from the stream.

func (*Client) HomeTimeline

func (c *Client) HomeTimeline(ctx context.Context, latest bool, count int, cursor string) (*models.Page, error)

HomeTimeline fetches the authenticated home timeline. When latest is true it returns the chronological "Following" feed instead of "For You".

func (*Client) JoinCommunity

func (c *Client) JoinCommunity(ctx context.Context, communityID string) error

JoinCommunity joins the Community with the given id.

func (*Client) LeaveCommunity

func (c *Client) LeaveCommunity(ctx context.Context, communityID string) error

LeaveCommunity leaves the Community with the given id.

func (*Client) Like

func (c *Client) Like(ctx context.Context, tweetID string) error

Like favourites a tweet.

func (*Client) Likes

func (c *Client) Likes(ctx context.Context, userID string, count int, cursor string) (*models.Page, error)

Likes fetches the tweets a user has liked, by numeric user id.

func (*Client) LikesByScreenName

func (c *Client) LikesByScreenName(ctx context.Context, screenName string, count int, cursor string) (*models.Page, error)

LikesByScreenName resolves a @handle then fetches that user's likes.

func (*Client) ListMembers

func (c *Client) ListMembers(ctx context.Context, listID string, count int, cursor string) (*models.UserPage, error)

ListMembers returns the accounts that belong to a List (its members), by the List's numeric id.

func (*Client) ListTweets

func (c *Client) ListTweets(ctx context.Context, listID string, count int, cursor string) (*models.Page, error)

ListTweets fetches the latest tweets of a List by its id.

func (*Client) Me

func (c *Client) Me(ctx context.Context) (*models.UserProfile, error)

Me returns the authenticated user's own profile. It resolves the logged-in screen name via the v1.1 account/settings endpoint, then fetches the full profile through the GraphQL UserByScreenName path.

func (*Client) Mentions

func (c *Client) Mentions(ctx context.Context, count int, maxID string) (*models.Page, error)

Mentions fetches tweets mentioning the authenticated user via the v1.1 mentions_timeline. Pagination is id-based: the returned NextCursor is the max_id for the next (older) page.

func (*Client) Mute

func (c *Client) Mute(ctx context.Context, screenName string) error

func (*Client) Notifications

func (c *Client) Notifications(ctx context.Context, tab string, count int, cursor string) (*NotificationPage, error)

Notifications fetches the v2 notifications timeline. tab is one of "all", "mentions", or "verified" (defaults to "all").

func (*Client) PinTweet

func (c *Client) PinTweet(ctx context.Context, tweetID string) error

PinTweet pins one of the authenticated account's own tweets to its profile.

func (*Client) Post

func (c *Client) Post(ctx context.Context, text string, opts PostOptions) (*models.Tweet, error)

Post creates a tweet, reply, or quote and returns the created tweet.

func (*Client) PostPoll

func (c *Client) PostPoll(ctx context.Context, text string, choices []string, durationMinutes int) (*models.Tweet, error)

PostPoll creates a poll card (2–4 text choices, duration in minutes) and posts a tweet carrying it.

func (*Client) RemoveListMember

func (c *Client) RemoveListMember(ctx context.Context, listID, userID string) error

RemoveListMember removes a user (by numeric id) from a List the account owns.

func (*Client) Retweet

func (c *Client) Retweet(ctx context.Context, tweetID string) error

Retweet reposts a tweet.

func (*Client) Retweeters

func (c *Client) Retweeters(ctx context.Context, tweetID string, count int, cursor string) (*models.UserPage, error)

Retweeters returns the accounts that retweeted a tweet.

func (*Client) ScheduleTweet

func (c *Client) ScheduleTweet(ctx context.Context, text string, executeAt int64, mediaIDs []string) (string, error)

ScheduleTweet queues a tweet for publication at executeAt (unix seconds) and returns the scheduled tweet id. mediaIDs are optional attached media.

func (*Client) ScheduledTweets

func (c *Client) ScheduledTweets(ctx context.Context) ([]ScheduledTweet, error)

ScheduledTweets lists the account's pending scheduled tweets, soonest first.

func (*Client) Search

func (c *Client) Search(ctx context.Context, query, product string, count int, cursor string) (*models.Page, error)

Search runs an advanced search. product is one of Top, Latest, People, Photos, Videos.

func (*Client) SendDM

func (c *Client) SendDM(ctx context.Context, recipientID, text string) error

SendDM sends a direct message to a recipient user id via the v1.1 DM events endpoint. Resolve a @handle to an id with UserByScreenName first.

func (*Client) SendDMMedia

func (c *Client) SendDMMedia(ctx context.Context, recipientID, text string, data []byte, mimeType string) error

SendDMMedia uploads media (DM category) and sends it as a DM attachment, with optional accompanying text.

func (*Client) SetAltText

func (c *Client) SetAltText(ctx context.Context, mediaID, text string) error

SetAltText attaches accessibility alt text to an uploaded media id (call after UploadMedia, before posting).

func (*Client) SetQueryID

func (c *Client) SetQueryID(op, id string)

SetQueryID overrides a single operation's query id (used when x.com rotates them and a fresh id is discovered).

func (*Client) Settings

func (c *Client) Settings(ctx context.Context) (map[string]any, error)

Settings returns the authenticated account's settings (privacy, DM, discovery) via the v1.1 account/settings endpoint.

func (*Client) SubscribeList

func (c *Client) SubscribeList(ctx context.Context, listID string) error

SubscribeList follows (subscribes to) a List owned by anyone, so it appears in the authenticated account's Lists.

func (*Client) TrendLocations

func (c *Client) TrendLocations(ctx context.Context) ([]TrendLocation, error)

TrendLocations lists the places (with WOEIDs) that have trending data, via the v1.1 trends/available endpoint.

func (*Client) Trends

func (c *Client) Trends(ctx context.Context, woeid string) ([]Trend, error)

Trends returns the trending topics for a WOEID location (1 = worldwide) via the v1.1 trends/place endpoint.

func (*Client) TweetDetail

func (c *Client) TweetDetail(ctx context.Context, tweetID string) (*models.Page, error)

TweetDetail fetches a tweet and its conversation thread.

func (*Client) Unblock

func (c *Client) Unblock(ctx context.Context, screenName string) error

func (*Client) Unbookmark

func (c *Client) Unbookmark(ctx context.Context, tweetID string) error

Unbookmark removes a saved tweet.

func (*Client) Unfollow

func (c *Client) Unfollow(ctx context.Context, screenName string) error

func (*Client) UnfollowTopic

func (c *Client) UnfollowTopic(ctx context.Context, topicID string) error

func (*Client) Unlike

func (c *Client) Unlike(ctx context.Context, tweetID string) error

Unlike removes a favourite.

func (*Client) Unmute

func (c *Client) Unmute(ctx context.Context, screenName string) error

func (*Client) UnpinTweet

func (c *Client) UnpinTweet(ctx context.Context, tweetID string) error

UnpinTweet removes the pinned tweet from the authenticated account's profile.

func (*Client) Unretweet

func (c *Client) Unretweet(ctx context.Context, tweetID string) error

Unretweet undoes a repost.

func (*Client) UnsubscribeList

func (c *Client) UnsubscribeList(ctx context.Context, listID string) error

UnsubscribeList unfollows a List the authenticated account subscribed to.

func (*Client) UpdateAvatar

func (c *Client) UpdateAvatar(ctx context.Context, image []byte) error

UpdateAvatar sets the account's profile picture from raw image bytes.

func (*Client) UpdateBanner

func (c *Client) UpdateBanner(ctx context.Context, image []byte) error

UpdateBanner sets the account's profile banner from raw image bytes.

func (*Client) UpdateProfile

func (c *Client) UpdateProfile(ctx context.Context, f ProfileFields) error

UpdateProfile edits the authenticated account's profile (name, bio, location, url) via the v1.1 account/update_profile endpoint. Only the non-empty fields are sent.

func (*Client) UpdateSettings

func (c *Client) UpdateSettings(ctx context.Context, fields map[string]string) error

UpdateSettings posts the given fields to account/settings (e.g. protected, allow_dms_from, discoverable_by_email). Only the provided keys are changed.

func (*Client) UploadMedia

func (c *Client) UploadMedia(ctx context.Context, data []byte, mediaType, category string) (string, error)

UploadMedia performs a chunked INIT/APPEND/FINALIZE upload and returns the media_id to attach to a tweet. mediaType is the MIME type (e.g. image/jpeg); category is the x.com media_category (tweet_image / tweet_video / tweet_gif), derived automatically when empty. Video/gif uploads are polled to completion.

func (*Client) UserByRestId

func (c *Client) UserByRestId(ctx context.Context, userID string) (*models.UserProfile, error)

UserByRestId resolves a profile by its numeric user id (the counterpart to UserByScreenName).

func (*Client) UserByScreenName

func (c *Client) UserByScreenName(ctx context.Context, screenName string) (*models.UserProfile, error)

UserByScreenName resolves a profile by @handle.

func (*Client) UserMedia

func (c *Client) UserMedia(ctx context.Context, userID string, count int, cursor string) (*models.Page, error)

UserMedia fetches the photos/videos tab of a user's profile by numeric id.

func (*Client) UserPosts

func (c *Client) UserPosts(ctx context.Context, screenName string, count int, cursor string) (*models.Page, error)

UserPosts is a convenience wrapper that resolves a @handle then fetches posts.

func (*Client) UserTweets

func (c *Client) UserTweets(ctx context.Context, userID string, count int, cursor string) (*models.Page, error)

UserTweets fetches a user's posts by numeric user id.

func (*Client) VotePoll

func (c *Client) VotePoll(ctx context.Context, tweetID string, choice int) error

VotePoll casts a vote (choice 1..N) on the poll attached to a tweet. It first reads the tweet to recover the poll card's uri and name, then submits the vote through the cards passthrough endpoint.

type DirectMessage

type DirectMessage struct {
	ID               string         `json:"id"`
	ConversationID   string         `json:"conversationId,omitempty"`
	Text             string         `json:"text"`
	SenderID         string         `json:"senderId"`
	SenderScreenName string         `json:"senderScreenName,omitempty"`
	RecipientID      string         `json:"recipientId,omitempty"`
	Media            []models.Media `json:"media,omitempty"` // attached photo/video/gif
	CreatedAt        string         `json:"createdAt"`       // unix millis as returned by x.com
}

DirectMessage is a single DM, normalised from the inbox state.

type Draft

type Draft struct {
	ID   string `json:"id"`
	Text string `json:"text,omitempty"`
}

Draft is an unsent draft tweet.

type LoginResult

type LoginResult struct {
	AuthToken string
	CT0       string
}

LoginResult carries the cookies obtained from a successful password login.

func Login

func Login(ctx context.Context, username, password, proxyURL string) (*LoginResult, error)

Login performs x.com's onboarding "login" flow with a username/handle and password, returning the resulting auth_token and ct0 cookies. It cannot solve interactive challenges (2FA codes, e-mail/phone verification) and returns a descriptive error when one is required. proxyURL (optional, http(s):// or socks5://) routes every request — useful because x.com blocks login from datacenter IPs, so a residential proxy is usually required.

type NotificationItem

type NotificationItem struct {
	Kind      string        `json:"kind"` // "notification" or "tweet"
	ID        string        `json:"id,omitempty"`
	Message   string        `json:"message,omitempty"`
	Icon      string        `json:"icon,omitempty"` // template icon, e.g. heart_icon
	Timestamp string        `json:"timestampMs,omitempty"`
	Tweet     *models.Tweet `json:"tweet,omitempty"`
}

NotificationItem is one row of the notifications timeline: either a notification message ("X and 3 others liked your post") or a tweet surfaced in the tab (e.g. a mention/reply).

type NotificationPage

type NotificationPage struct {
	Items      []NotificationItem `json:"items"`
	NextCursor string             `json:"nextCursor,omitempty"`
}

NotificationPage is a page of notifications plus a pagination cursor.

type Option

type Option func(*Client)

Option customises a Client.

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient overrides the HTTP client (e.g. to plug in a utls transport for JA3 impersonation, or a proxy).

func WithLocale

func WithLocale(l string) Option

WithLocale sets the x-twitter-client-language header (default "en").

func WithTransactionProvider

func WithTransactionProvider(p *transaction.Provider) Option

WithTransactionProvider shares a pre-warmed transaction.Provider.

func WithUTLS

func WithUTLS() Option

WithUTLS makes the client dial TLS through uTLS, sending a Chrome-like ClientHello (JA3) so authenticated traffic better matches real browser fingerprints — the same goal as the per-request x-client-transaction-id, one layer lower. ALPN advertises both h2 and http/1.1; whichever the server negotiates is used (so HTTP/2 is preserved over the Chrome fingerprint).

type PostOptions

type PostOptions struct {
	// ReplyToID, when set, makes this a reply.
	ReplyToID string
	// QuoteTweetID, when set, makes this a quote tweet.
	QuoteTweetID string
	// MediaIDs are pre-uploaded media ids (see UploadMedia) to attach.
	MediaIDs []string
	// CardURI, when set (e.g. a poll card), attaches a card to the tweet.
	CardURI string
	// EditTweetID, when set, edits that existing tweet (Premium-gated).
	EditTweetID string
}

PostOptions configures a tweet creation.

type ProfileFields

type ProfileFields struct {
	Name        string // display name
	Description string // bio
	Location    string
	URL         string
}

ProfileFields are the editable profile attributes. Empty fields are omitted, so callers can update just the ones they pass.

type RateLimit

type RateLimit struct {
	Limit     int   `json:"limit"`
	Remaining int   `json:"remaining"`
	ResetAt   int64 `json:"resetAt"` // unix seconds
}

RateLimit is a snapshot of an endpoint's x-rate-limit-* headers.

func LastRateLimit

func LastRateLimit() *RateLimit

LastRateLimit returns the most recently observed rate-limit snapshot, or nil if no rate-limited response has been seen yet.

type ScheduledTweet

type ScheduledTweet struct {
	ID        string `json:"id"`
	ExecuteAt string `json:"executeAt,omitempty"` // unix seconds
	State     string `json:"state,omitempty"`     // e.g. "Scheduled"
	Text      string `json:"text,omitempty"`
}

ScheduledTweet is a tweet queued for future publication.

type Trend

type Trend struct {
	Name        string `json:"name"`
	URL         string `json:"url,omitempty"`
	TweetVolume int    `json:"tweetVolume,omitempty"`
}

Trend is a single trending topic.

type TrendLocation

type TrendLocation struct {
	Name    string `json:"name"`
	WOEID   int    `json:"woeid"`
	Country string `json:"country,omitempty"`
}

TrendLocation is a place trends are available for (WOEID + name).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL