> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xquik.com/llms.txt
> Use this file to discover all available pages before exploring further.

# X (Twitter) API Go tweet search to CSV & JSON lines

> Search tweets with the Xquik Go SDK, follow cursors, and save rows as JSON Lines, CSV, or XLSX for workers, queues, and analysts in your own apps and jobs.

> For the complete documentation index, see [llms.txt](https://docs.xquik.com/llms.txt).

This guide builds on the [Go SDK setup](https://docs.xquik.com/sdks/go.md), which covers install and authentication.

## Tweet search workflow to JSON Lines, CSV, or XLSX

Search newest tweets with `client.X.Tweets.Search` through `GET /x/tweets/search`. Write each tweet as a JSON line for queues, data lakes, CSV, or XLSX.

```go theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/bash.json","/languages/csharp.json","/languages/go.json","/languages/java.json","/languages/javascript.json","/languages/kotlin.json","/languages/php.json","/languages/python.json","/languages/ruby.json","/languages/typescript.json"]}}
package main

import (
	"context"
	"encoding/json"
	"os"

	"github.com/Xquik-dev/x-twitter-scraper-go"
	"github.com/Xquik-dev/x-twitter-scraper-go/option"
)

func main() {
	client := xtwitterscraper.NewClient(
		option.WithAPIKey(os.Getenv("X_TWITTER_SCRAPER_API_KEY")),
	)

	out, err := os.Create("xquik-tweet-search.jsonl")
	if err != nil {
		panic(err)
	}
	defer out.Close()

	encoder := json.NewEncoder(out)
	cursor := ""

	for {
		params := xtwitterscraper.XTweetSearchParams{
			Q:         "from:username webhook OR SDK",
			QueryType: xtwitterscraper.XTweetSearchParamsQueryTypeLatest,
		}
		if cursor != "" {
			params.Cursor = xtwitterscraper.String(cursor)
		}

		page, err := client.X.Tweets.Search(context.Background(), params)
		if err != nil {
			panic(err)
		}

		for _, tweet := range page.Tweets {
			if err := encoder.Encode(tweet); err != nil {
				panic(err)
			}
		}

		if !page.HasNextPage || page.NextCursor == "" {
			break
		}
		cursor = page.NextCursor
	}
}
```

The example builds an `XTweetSearchParams` request so the Go fields stay aligned with `GET /x/tweets/search`. The generated params map directly to the REST endpoint.

> [card] Q
>
> Go field `Q` maps to REST `q`. It holds the required X (Twitter) search query with keywords, handles, hashtags, or operators.

> [card] Limit
>
> Go field `Limit` maps to REST `limit`. Use it as a 1 to 200 upper bound for a bounded pull. If `page.HasNextPage` is true, keep the same `Q`, filters, `QueryType`, and `Limit`. Then continue with `page.NextCursor`.

> [card] Cursor
>
> Go field `Cursor` maps to REST `cursor`. Pass the opaque cursor from `NextCursor` to request the next page.

> [card] SinceTime
>
> Go field `SinceTime` maps to REST `sinceTime`. Use the inclusive ISO bound on every page.

> [card] UntilTime
>
> Go field `UntilTime` maps to REST `untilTime`. Use the exclusive ISO bound on every page.

> [card] QueryType
>
> Go field `QueryType` maps to REST `queryType`. Use `Latest` for chronological results or `Top` for engagement-ranked results.

## Returned data & handoff

`client.X.Tweets.Search` returns `PaginatedTweets`.

> [card] Tweets
>
> JSON field `tweets`. Contains tweet records with `ID`, `Text`, `Author`, and `CreatedAt`. Records also carry `LikeCount`, `ReplyCount`, `RetweetCount`, `QuoteCount`, `BookmarkCount`, `ViewCount`, and `IsNoteTweet` when available.

> [card] HasNextPage
>
> Go field `HasNextPage`. JSON field `has_next_page`. Tells your worker whether another page exists.

> [card] NextCursor
>
> JSON field `next_cursor`. Store it only when `page.HasNextPage` is true. For bounded pulls that return fewer tweets than `Limit`, pass it back as `Cursor`. Send the same query, filters, `QueryType`, and `Limit` with that cursor.

Write `Tweets` as JSON Lines to `xquik-tweet-search.jsonl` for queues and data lakes. Transform the projected records into CSV for analysts. When account teams need spreadsheets, produce XLSX from those rows. Pass `ID`, `Text`, `Author.Username`, `CreatedAt`, and engagement counts into your CRM or enrichment pipeline. For explicit `Limit` pulls, resume with the same query, filters, `QueryType`, and `Limit`. Only `Cursor` changes.

## Next steps

* [Go SDK setup](https://docs.xquik.com/sdks/go.md)
* [Follower export](https://docs.xquik.com/sdks/go-follower-export.md)
* [Media tweets](https://docs.xquik.com/sdks/go-media-tweets.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.