By Sorsa Editorial

Published June 2026: reflects X's current pay-per-use pricing (including the April 2026 write-cost changes) and the state of Go tooling, where X ships official SDKs only for Python and TypeScript, not Go.

Key Takeaway: There is no official X (Twitter) API SDK for Go in 2026; X ships official SDKs only for Python and TypeScript. The practical routes in Go are a maintained community library such as gotwtr, plain net/http with a bearer token, or a read-only third-party REST API.

If you searched "twitter api golang" expecting an official, supported package, there is not one. X shipped first-party SDKs for Python and TypeScript in late 2025 and left Go to the community. Most Go tutorials that rank for this query are worse than absent: they teach dghubble/go-twitter, which only speaks the retired v1.1 API, against pricing that no longer exists.

We build and run Sorsa API, an alternative Twitter/X API, and Go is a natural fit for the read-only path: it returns profiles, tweets, search results, and followers as clean JSON that maps straight into Go structs, with one API key in the ApiKey header, no OAuth handshake, and no developer-account approval to wait on. On read-heavy work it runs up to roughly 50x cheaper than the official X API, holds a flat 20 requests per second on every plan, and starts at $49 a month for 10,000 requests. Not every project fits that mold: some need to post, and some need the official API for compliance. This guide covers every Go route with working code, current pricing, and a concurrent collector that respects the rate limit. You can also test calls without writing code in the playground.

Table of contents


What Changed: the X API and Go Tooling in 2026

Three things changed for Go developers since the old tutorials were written. The X API moved to pay-per-use billing with no free tier and charges per resource read. Writing got more expensive after the April 2026 update. And X shipped its first official SDKs, but only for Python and TypeScript, so Go developers still rely on community libraries or raw HTTP.

Pay-per-use is the default. There is no free tier and no monthly Basic plan for new signups. You buy credits and pay per resource: $0.005 per post read, $0.010 per user profile, and $0.010 per follower or following record. Reading your own account's data costs $0.001 per resource, and standard accounts are capped at 2 million post reads per month. The numbers behind a real budget are in our X API pricing breakdown and the explainer on why X API pricing climbed.

Writing got more expensive. After the April 2026 update, a standard post costs $0.015 per request and a post that contains a URL costs $0.20. Follow, like, and quote-post actions were pulled from the self-serve tiers and now require an Enterprise contract.

Official SDKs landed for Python and TypeScript only. In late 2025 X announced first-party XDKs for those two languages. There is no official Go SDK. The community libraries fill the gap, and the strongest one for the v2 API is gotwtr, which covers the full v2 surface with an OAuth 2.0 bearer token.

The old Go libraries are mostly dead. dghubble/go-twitter, the library nearly every older Go tutorial uses, targets the v1.1 API that X retired. Any guide that calls client.Statuses.Update or client.Search.Tweets with v1.1 fields is out of date.


The Best Go Library for the X API

For new v2 work in Go, gotwtr is the best general-purpose library: it targets the v2 API, authenticates with an OAuth 2.0 bearer token, and covers users, tweets, search, followers, timelines, and writes. There is no official Go SDK to prefer over it. For read-only data collection, many Go teams skip libraries and call a third-party REST API with the standard net/http package, which removes OAuth entirely.

Here is how the main options compare.

Library / toolAPI versionBest forNotes
gotwtrv2New v2 builds, full coverageBearer token. Covers search, users, followers, timelines, plus writes and streaming. Actively maintained.
gotwiv2Typed, modular v2 accessPackage-per-endpoint design, bearer and OAuth 1.0a. Still marked under development.
go-twitter (dghubble)v1.1 onlyLegacy code onlyMature but speaks the retired v1.1 API. Most old tutorials use it; not for new work.
net/http (standard library)anyMinimal dependencies, full controlYou define request structs and pagination. Pairs well with a third-party API.
Read-only REST APIn/aRead-heavy data collectionOne key in a header, no OAuth, flat per-request billing. Read-only.

Whichever library you pick for the official API, the cost is identical, because X bills per resource on its side, not per library. The variable you control is how many resources you pull, which is where batch endpoints and a flat-rate API change the math.


Which Approach Should You Use?

Pick the route before writing code. For read and write against the v2 API with a typed library, use gotwtr. For read-only data at volume with minimal setup, a third-party REST API removes OAuth and the approval queue. For full control with no dependencies, the standard net/http package is enough. The decision is mostly read versus write, and how much volume you pull.

If you need...Use...
Read and write with a v2 librarygotwtr
Read-only data at scale, minimal setupA read-only third-party REST API
Full control, no dependenciesPlain net/http with a bearer token
To post, like, or followgotwtr or the official API (OAuth required)

If your project only reads public data, a third-party API removes the OAuth flow: one key in a header and you start pulling data, with no developer-account application and no credit purchase. If you need to post or run write actions, the official API through gotwtr is the path; no third-party provider posts on your behalf. Working in another language? See the Python version of this guide.


Method 1: a Community Library (gotwtr)

gotwtr is a Go client for the X API v2. It authenticates with an OAuth 2.0 bearer token, returns typed responses, and covers the full v2 endpoint set. It is the closest thing Go has to a complete, current Twitter client.

Install it:

bash
go get github.com/sivchari/gotwtr

Search the last seven days and print the results:

go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/sivchari/gotwtr"
)

func main() {
	client := gotwtr.New(os.Getenv("X_API_BEARER_TOKEN"))

	tsr, err := client.SearchRecentTweets(context.Background(), "golang lang:en", &gotwtr.SearchTweetsOption{
		TweetFields: []gotwtr.TweetField{gotwtr.TweetFieldAuthorID, gotwtr.TweetFieldCreatedAt},
		MaxResults:  20,
	})
	if err != nil {
		panic(err)
	}

	for _, t := range tsr.Tweets {
		fmt.Println(t.Text)
	}
}

Look up specific tweets by ID:

go
ts, err := client.RetrieveMultipleTweets(context.Background(), []string{"1782368585664626774"})
if err != nil {
	panic(err)
}

for _, t := range ts.Tweets {
	fmt.Println(t.Text)
}

gotwtr also covers user lookup (RetrieveSingleUserWithUserName), follower and following lists (Followers, Following), user timelines (UserTweetTimeline), writes (PostTweet), and filtered or sampled streaming (ConnectToStream, VolumeStreams). It is the right pick when you want typed v2 access and may also write. The tradeoffs: it is community-maintained rather than first-party, you still need a paid X developer account, and you pay X's per-resource pricing on every call.


Method 2: plain net/http With a Bearer Token

No library, no wrapper. Go's standard net/http package and encoding/json are enough to call the X API v2 with a bearer token. This route suits developers who want full control over requests and response structs, or who prefer to avoid third-party dependencies.

Define a struct for the fields you want and look up a profile:

go
package main

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

type userResponse struct {
	Data struct {
		ID            string `json:"id"`
		Username      string `json:"username"`
		Name          string `json:"name"`
		PublicMetrics struct {
			FollowersCount int `json:"followers_count"`
		} `json:"public_metrics"`
	} `json:"data"`
}

func main() {
	req, _ := http.NewRequest(http.MethodGet, "https://api.x.com/2/users/by/username/elonmusk", nil)

	q := req.URL.Query()
	q.Set("user.fields", "public_metrics,created_at")
	req.URL.RawQuery = q.Encode()
	req.Header.Set("Authorization", "Bearer "+os.Getenv("X_API_BEARER_TOKEN"))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var u userResponse
	json.NewDecoder(resp.Body).Decode(&u)

	fmt.Printf("@%s has %d followers\n", u.Data.Username, u.Data.PublicMetrics.FollowersCount)
}

The official API paginates search with a next_token in the response meta. Page through every result with a guard so a broad query does not exhaust your quota:

go
func searchRecent(token, query string) ([]map[string]any, error) {
	var all []map[string]any
	nextToken := ""

	for {
		req, _ := http.NewRequest(http.MethodGet, "https://api.x.com/2/tweets/search/recent", nil)
		q := req.URL.Query()
		q.Set("query", query)
		q.Set("max_results", "100")
		q.Set("tweet.fields", "created_at,public_metrics")
		if nextToken != "" {
			q.Set("next_token", nextToken)
		}
		req.URL.RawQuery = q.Encode()
		req.Header.Set("Authorization", "Bearer "+token)

		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			return nil, err
		}

		var body struct {
			Data []map[string]any `json:"data"`
			Meta struct {
				NextToken string `json:"next_token"`
			} `json:"meta"`
		}
		json.NewDecoder(resp.Body).Decode(&body)
		resp.Body.Close()

		all = append(all, body.Data...)
		if body.Meta.NextToken == "" {
			break
		}
		nextToken = body.Meta.NextToken
	}

	return all, nil
}

This works when you want zero dependencies or you are debugging API behavior. The downside is that you own pagination, status-code handling, rate limiting, and retries. For a one-off job that is fine; for a production pipeline you end up writing a small client of your own. This route still requires a developer account and pay-per-use credits.


Method 3: a Read-Only REST API

If a Go service only reads public Twitter data, a third-party REST API skips the official API entirely: no OAuth, no application step, no credit-purchase workflow, just one key in a header and JSON that decodes straight into structs.

This is the practical route to getting X data without a developer account. Here is what it looks like with Sorsa, using nothing but the standard library.

Get a user profile:

go
package main

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

type sorsaUser struct {
	ID             string `json:"id"`
	Username       string `json:"username"`
	DisplayName    string `json:"display_name"`
	FollowersCount int    `json:"followers_count"`
}

func main() {
	req, _ := http.NewRequest(http.MethodGet, "https://api.sorsa.io/v3/info?username=elonmusk", nil)
	req.Header.Set("ApiKey", os.Getenv("SORSA_API_KEY"))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var u sorsaUser
	json.NewDecoder(resp.Body).Decode(&u)

	fmt.Printf("@%s (%s): %d followers\n", u.Username, u.DisplayName, u.FollowersCount)
}

Search tweets with the full web operator set. The search endpoint returns about 20 tweets per page and a next_cursor for the next page:

go
import "bytes"

type sorsaTweet struct {
	ID         string `json:"id"`
	FullText   string `json:"full_text"`
	LikesCount int    `json:"likes_count"`
}

type searchResponse struct {
	Tweets     []sorsaTweet `json:"tweets"`
	NextCursor string       `json:"next_cursor"`
}

func searchTweets(apiKey, query string) (*searchResponse, error) {
	payload, _ := json.Marshal(map[string]string{"query": query, "order": "latest"})

	req, _ := http.NewRequest(http.MethodPost, "https://api.sorsa.io/v3/search-tweets", bytes.NewReader(payload))
	req.Header.Set("ApiKey", apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var out searchResponse
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return nil, err
	}
	return &out, nil
}

Pull a follower list. One request returns up to 200 profiles, so a 1,000-follower account is five requests instead of ten paginated pages:

go
type followersResponse struct {
	Users      []sorsaUser `json:"users"`
	NextCursor string      `json:"next_cursor"`
}

// GET https://api.sorsa.io/v3/followers?username=elonmusk returns up to 200 users

For complex queries, combine operators the way you would in advanced search; the full list is in our search operator reference, and the endpoint searches the full tweet archive. Each tweet response carries the author profile and the public metrics, so reading tweet metrics via API and fetching follower lists adds no extra calls. The header is ApiKey, the base URL is https://api.sorsa.io/v3, and the field names match the API documentation exactly. To pull up to 100 tweets in one request, post their IDs to /tweet-info-bulk, which counts as a single request and returns complete tweet objects. There is also a step-by-step guide to searching tweets via API.


Is There an Official Go SDK for the X API?

No. As of 2026 X publishes official SDKs only for Python and TypeScript; there is no official Go SDK. X's own tools-and-libraries page lists those two first-party SDKs plus developer tools, and the open-source XDK generator currently ships templates only for Python and TypeScript, with Go documented as a future contribution target rather than a released package.

For Go, that leaves three real options, all covered above: the community library gotwtr for typed v2 access, plain net/http for full control, or a read-only third-party API for read-heavy work. For quick manual checks without writing Go at all, X also ships xurl, an official curl-like command-line tool with built-in OAuth, which is useful for poking at endpoints before you wire them into code.

If a Go SDK does land later, it will be generated from the same OpenAPI specification as the Python and TypeScript ones, so its surface will resemble those. Until then, treat any tutorial claiming an "official Go SDK" as inaccurate.


Building a Concurrent Data Collector in Go

Go's real advantage for data collection is concurrency, but concurrency against a rate-limited API needs a throttle, or you trade 429 errors for speed. The pattern that works: fan out requests across goroutines, gate them through a single rate limiter sized to the API's limit, and collect results under a mutex. Against a flat 20 requests per second limit, a ticker that releases one slot every 50 milliseconds keeps every goroutine inside the budget.

This collector fetches recent tweets for many queries at once while staying under the limit. It reuses the searchTweets function and sorsaTweet struct from Method 3.

go
package main

import (
	"fmt"
	"sync"
	"time"
)

func collectForQueries(apiKey string, queries []string) map[string][]sorsaTweet {
	const ratePerSecond = 20
	ticker := time.NewTicker(time.Second / ratePerSecond) // one slot every 50ms
	defer ticker.Stop()

	results := make(map[string][]sorsaTweet)
	var mu sync.Mutex
	var wg sync.WaitGroup

	for _, query := range queries {
		wg.Add(1)
		go func(q string) {
			defer wg.Done()

			<-ticker.C // wait for a rate-limit slot before calling
			res, err := searchTweets(apiKey, q)
			if err != nil {
				return
			}

			mu.Lock()
			results[q] = res.Tweets
			mu.Unlock()
		}(query)
	}

	wg.Wait()
	return results
}

func main() {
	queries := []string{"golang", "rustlang", "typescript"}
	all := collectForQueries("YOUR_SORSA_API_KEY", queries)
	for q, tweets := range all {
		fmt.Printf("%s: %d tweets\n", q, len(tweets))
	}
}

The ticker is doing the real work: every goroutine blocks on it, so no matter how many you launch, calls leave at the allowed rate. When we rebuilt our own collectors, a flat per-second limit turned out simpler to pace against than per-endpoint windows, because a single ticker covers the whole client instead of separate budgets per endpoint. To walk past the first page of each query, follow the next_cursor in the response and stop on an empty value; the pagination guide has the loop, and the official side is in our X API rate limits reference. On a 429, wait one second and retry the same call.


Comparison: Three Routes, Side by Side

The three Go routes split on two axes: whether you can write, and how you are billed. Both official-API routes need a developer account and bill per resource. A read-only API trades write access for a single key and flat per-request billing.

RouteSetupAuthReadsWritesBilling
gotwtr (community v2 library)Developer account, creditsBearer / OAuthYesYesPer resource
Plain net/httpDeveloper account, creditsBearer / OAuthYesYesPer resource
Read-only REST APIAPI key, about 3 minutesSingle ApiKey headerYesNo (read-only)Flat per request

The split tells you which to pick: if you need to post or run write actions, that is the official API's territory through gotwtr. For read-heavy access at a flat, predictable price, a read-only API is the cheaper and simpler route, and it returns the same public data.

The cost gap on reads comes from the billing unit. The official API charges for every post and every author profile in a response; a flat-rate API charges one request regardless of how many items it returns.

WorkloadOfficial X APIRead-only API (Sorsa Pro)
Search returning 20 tweets, with author data$0.30 (20 x $0.005 plus 20 x $0.010)One request, about $0.002 (authors included)
1,000 follower profilesAbout $10 (per profile)About $0.01 (5 requests at 200 per page)
100 tweets by ID, with author data$1.50 (100 x $0.005 plus 100 x $0.010)One request, about $0.002 (bulk endpoint)
Monthly cap2 million post readsPlan based (10,000 to 500,000 requests)
Rate limit300 to 900 per 15 minutes (varies)20 requests per second, flat

For read-heavy work the per-resource model is the expensive way to do a simple job, which is why a flat per-request rate wins once you cross roughly 10,000 reads a month. Writes are the exception: posting and DMs live only on the official API, so a write-heavy service belongs there regardless of read cost.


How to Get Your API Credentials

For the official API, create a developer account at developer.x.com, agree to the developer terms, describe your use case, and create a Project and App to generate a bearer token and OAuth credentials. Buy credits before your first call, since there is no free tier. For a read-only third-party API, sign up, generate a key, and pass it in a header, with no application or approval step.

Read either credential from the environment, never from source:

bash
# .env or your shell environment
X_API_BEARER_TOKEN=your-x-bearer-token
SORSA_API_KEY=your-sorsa-api-key

In Go, read them with os.Getenv as shown in the examples above; for .env file loading in development, a package like godotenv is optional. If you are porting existing official-API code, the migration guide maps the official endpoints and field names to their flat-rate equivalents so you can change the transport without rewriting the logic.


In Practice: Cutting the Cost of a Go Collector

A roughly 12-person market-intelligence team came to us running a Go service that tracked competitor accounts. It used a v1.1 era library, which broke when X retired those endpoints, so the team rewrote it against the official v2 API with plain net/http. The code was clean; the bill was not. Every nightly run paid per post read and per author profile, and the 2-million-post-reads monthly cap meant they watched volume as their tracked-account list grew.

The fix was a transport swap, not a rewrite. They kept the goroutine collection logic and the scheduling, pointed the client at the search and /followers endpoints, and dropped OAuth for a single ApiKey header. Because each request returns up to 20 tweets or 200 follower profiles instead of billing per resource, the same nightly pull cost a fraction of what it had, roughly 30 to 50 times less on the read-heavy parts, and a per-second limit replaced the monthly cap as the only thing to pace against. For a read-only workload, the per-resource model had been the expensive way to do a simple job.


FAQ

Is there an official X (Twitter) API SDK for Go?

No. As of 2026 X publishes official SDKs only for Python and TypeScript; there is no official Go SDK. The maintained community option for the v2 API is gotwtr, which uses an OAuth 2.0 bearer token and covers users, tweets, search, followers, and timelines. X's open-source SDK generator lists Go as a future target, but no Go package has been released, so treat any "official Go SDK" claim as inaccurate.

What is the best Go library for the Twitter API?

For new v2 work, gotwtr is the best general-purpose Go library: it targets the v2 API, authenticates with a bearer token, and covers reads and writes. The older go-twitter package by dghubble is widely cited but speaks only the retired v1.1 API, so it is not suitable for new builds. For read-only data at volume, many Go teams skip libraries and call a third-party REST API with the standard net/http package.

How do you get tweets in Go without a developer account?

Call a read-only third-party REST API. With Sorsa, you sign up, get an API key, pass it in the ApiKey header, and send a request with net/http; the JSON decodes straight into Go structs. There is no OAuth flow, no app review, and no credit purchase, and each tweet response includes the author profile and public metrics, so a single request returns complete data.

How much does the X API cost for a Go app in 2026?

On the official X API you pay per resource: $0.005 per post read, $0.010 per user profile, $0.015 per standard post, and $0.20 for a post with a URL, with a 2 million post reads monthly cap. A search returning 20 tweets costs $0.30 once author profiles are included. Sorsa bills per request on flat plans from $49 a month for 10,000 requests, and each request returns up to 20 tweets or 200 follower profiles.

How do you handle X API rate limits in Go?

The official API limits requests per 15-minute window (typically 300 to 900 depending on the endpoint) and returns a 429 when you hit one. In Go, gate concurrent calls through a single rate limiter, such as a time.Ticker or golang.org/x/time/rate, sized to the limit, so goroutines do not exceed it. A flat-rate API like Sorsa uses a per-second limit of 20 requests, so a ticker releasing one slot every 50 milliseconds keeps you inside the budget.

Can you use net/http alone to call the X API in Go?

Yes. Go's standard net/http and encoding/json packages can call the X API v2 with a bearer token in the Authorization header and decode the response into your own structs. You handle pagination, status codes, and retries yourself, which is fine for a few endpoints or a one-off job. For a larger pipeline you end up writing a small client, at which point a library or a third-party API saves time.

Does gotwtr support the X API v2?

Yes. gotwtr is built for the X API v2 and authenticates with an OAuth 2.0 bearer token. It covers search, user lookup, followers and following, timelines, and write actions such as posting, and it shipped full v2 endpoint coverage in its 1.x line. It requires a paid X developer account with purchased credits, since the official API has no free tier under pay-per-use.


Getting Started

Pick a route and run one of the examples above.

  • Read-only data: grab a key from the Sorsa dashboard, set it as SORSA_API_KEY, and run any Method 3 example. Structured X data lands in your terminal in under a minute, and the quickstart walks through the first call. Plans and limits are on the pricing page.
  • Read and write: create a developer account at developer.x.com, buy credits, and run gotwtr or the net/http examples with your bearer token.
  • Comparing providers: for a broader look at read-only options, see the Twitter API alternatives comparison, and for managed scraping tradeoffs, our guide to scraping X.

Reviewed by Keksich, founder of Sorsa, marketer and X API researcher.

How We Verified This Guide

We wrote and verified this guide in June 2026 while operating the API daily. The absence of an official Go SDK and the existence of the Python and TypeScript SDKs were confirmed against X's tools and libraries documentation and its developer announcement of the XDKs. The gotwtr method names and v2 coverage were checked against its package reference on the Go package index. X API pricing reflects the current pay-per-use model including the April 2026 write-cost changes. Sorsa endpoint behavior, per-request batching, and plan pricing come from the Sorsa API documentation; more about the team is on our About page. Library version numbers and star counts move, so they are described rather than pinned; for a current price the in-product docs are the source of truth.