> ## 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.

# Twitter scraper export API & CSV downloads

> Export tweet, follower, reply, profile, timeline, community, or list results in 7 formats, with documented CSV, XLSX, JSON, and PDF limits. Exports are free.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-extractions-export-200">
      ```text theme={null}
      <string>
      ```
    </Tab>

    <Tab title="400" id="response-extractions-export-400">
      ```json theme={null}
      {
        "error": "invalid_input",
        "message": "Invalid input. Check the request body."
      }
      ```
    </Tab>

    <Tab title="401" id="response-extractions-export-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required. Provide a valid API key or bearer token."
      }
      ```
    </Tab>

    <Tab title="404" id="response-extractions-export-404">
      ```json theme={null}
      {
        "error": "not_found",
        "message": "Resource not found."
      }
      ```
    </Tab>

    <Tab title="429" id="response-extractions-export-429">
      ```json theme={null}
      {
        "error": "rate_limit_exceeded",
        "message": "Too many requests. Try again later.",
        "retryAfter": 60
      }
      ```
    </Tab>
  </Tabs>
</Panel>

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

<Callout icon="circle-check" color="#16a34a">
  **Free.** This endpoint does not consume credits.
</Callout>

<CodeGroup>
  ```bash cURL theme={null}
  curl --fail -X GET "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=csv" \
    -H "x-api-key: xq_YOUR_KEY_HERE" \
    -o extraction-reply_extractor.csv
  ```

  ```javascript Node.js theme={null}
  import { writeFile } from "node:fs/promises";

  const extractionId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";
  const response = await fetch(
    `https://xquik.com/api/v1/extractions/${extractionId}/export?format=csv`,
    {
      method: "GET",
      headers: {
        "x-api-key": "xq_YOUR_KEY_HERE",
      },
    },
  );

  if (!response.ok) {
    throw new Error(`Export failed with ${response.status}`);
  }

  const bytes = Buffer.from(await response.arrayBuffer());
  await writeFile("extraction-reply_extractor.csv", bytes);
  ```

  ```python Python theme={null}
  import requests

  extraction_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  response = requests.get(
      f"https://xquik.com/api/v1/extractions/{extraction_id}/export",
      headers={"x-api-key": "xq_YOUR_KEY_HERE"},
      params={"format": "csv"},
  )
  response.raise_for_status()

  with open("extraction-reply_extractor.csv", "wb") as f:
      f.write(response.content)
  ```

  ```go Go theme={null}
  package main

  import (
      "fmt"
      "io"
      "net/http"
      "os"
  )

  func main() {
      req, err := http.NewRequest("GET", "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=csv", nil)
      if err != nil {
          panic(err)
      }
      req.Header.Set("x-api-key", "xq_YOUR_KEY_HERE")

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

      if resp.StatusCode < 200 || resp.StatusCode >= 300 {
          panic(fmt.Sprintf("export failed with %d", resp.StatusCode))
      }

      file, err := os.Create("extraction-reply_extractor.csv")
      if err != nil {
          panic(err)
      }
      defer file.Close()

      if _, err := io.Copy(file, resp.Body); err != nil {
          panic(err)
      }
  }
  ```
</CodeGroup>

## File handoff

Treat the response body as file bytes. Save it first, then pass the local path
to the CRM import, warehouse load, queue, or agent. Do not print downloaded
export bytes to shared logs.

```json theme={null}
{
  "extraction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "export_format": "csv",
  "export_file_path": "extraction-reply_extractor.csv",
  "content_type": "text/csv; charset=utf-8",
  "handoff_format": "file"
}
```

The response `Content-Disposition` header contains the server filename. Store it
when you need an audit trail that connects the downloaded file to the extraction
job.

### Format handoff map

<CardGroup cols={2}>
  <Card title="CRM CSV" icon="table">
    Use `format=csv` for CRM imports, spreadsheet checks, and follower or reply
    upserts. Name reply jobs `xquik-replies.csv` and follower jobs
    `xquik-followers.csv`.
  </Card>

  <Card title="App JSON" icon="braces">
    Use `format=json` for app ingestion, queue replay, or structured storage.
    Each row keeps the nested `enrichmentData` of its result, with media and
    entities. Store the extraction ID and server filename with the local path.
  </Card>

  <Card title="Analyst XLSX" icon="file-spreadsheet">
    Use `format=xlsx` for analyst review and account-management workbooks when
    people need filters or formulas.
  </Card>

  <Card title="Report formats" icon="file-text">
    Use `format=md`, `md-document`, `pdf`, or `txt` for human-readable reports.
    Xquik caps PDF at 10,000 rows.
  </Card>
</CardGroup>

For exports above 100,000 rows, use
[Extraction Workflow](/guides/extraction-workflow#durable-json-lines-handoff) to
write JSON Lines from paginated `GET /extractions/{id}` results.

## Headers

<ParamField header="x-api-key" type="string" required>
  Your API key. Session cookie authentication is also supported.
</ParamField>

## Path parameters

<ParamField path="id" type="string" required>
  Extraction job ID returned from [Create Extraction](/api-reference/extractions/create) or [List Extractions](/api-reference/extractions/twitter-scraping-job-history).
</ParamField>

## Query parameters

<ParamField query="format" type="string" required>
  Export file format. One of: `csv`, `json`, `md`, `md-document`, `pdf`, `txt`, `xlsx`.
</ParamField>

### Export filters

<ParamField query="minFollowers" type="integer">
  Minimum follower count.
</ParamField>

<ParamField query="maxFollowers" type="integer">
  Maximum follower count.
</ParamField>

<ParamField query="minFollowing" type="integer">
  Minimum following count.
</ParamField>

<ParamField query="maxFollowing" type="integer">
  Maximum following count.
</ParamField>

<ParamField query="minPosts" type="integer">
  Minimum post count.
</ParamField>

<ParamField query="maxPosts" type="integer">
  Maximum post count.
</ParamField>

<ParamField query="minLikes" type="integer">
  Minimum like count.
</ParamField>

<ParamField query="minReplies" type="integer">
  Minimum reply count.
</ParamField>

<ParamField query="minRetweets" type="integer">
  Minimum repost count.
</ParamField>

<ParamField query="minViews" type="integer">
  Minimum view count.
</ParamField>

<ParamField query="hasDescription" type="boolean">
  Require a non-empty description.
</ParamField>

<ParamField query="hasLocation" type="boolean">
  Require a non-empty location.
</ParamField>

<ParamField query="hasMedia" type="boolean">
  Require media.
</ParamField>

<ParamField query="verified" type="boolean">
  Match verified status.
</ParamField>

<ParamField query="lang" type="string">
  Match a language code.
</ParamField>

<ParamField query="search" type="string">
  Search exported result text.
</ParamField>

<ParamField query="sinceDate" type="string">
  Include results on or after this date.
</ParamField>

<ParamField query="untilDate" type="string">
  Include results on or before this date, inclusive.
</ParamField>

## Export columns

The extraction tool type decides the columns. Default exports include 29
columns. `article_extractor` exports 10 article columns. JSON rows also keep
each result's nested `enrichmentData`, as
[Get Extraction](/api-reference/extractions/twitter-extraction-results) returns it.

### Default result columns

All extraction tools except `article_extractor` use the default result column set. Some enrichment columns may be empty when the result does not include that data.

<CardGroup cols={2}>
  <Card title="User identity" icon="user">
    `User ID`, `Username`, `Display Name`, `Verified`, and `Profile Image`.
  </Card>

  <Card title="Audience metrics" icon="chart-no-axes-column">
    `Followers`, `Following`, `Posts`, `Media Count`, and `Favorites`.
  </Card>

  <Card title="Profile context" icon="file-text">
    `Description`, `Location`, and `Cover Picture`.
  </Card>

  <Card title="Tweet content" icon="message-square">
    `Tweet ID`, `Tweet URL`, `Tweet Text`, and `Tweet Created At`.
    `Tweet URL` falls back to the status URL when the username is unavailable.
  </Card>

  <Card title="Tweet engagement" icon="activity">
    `Likes`, `Reposts`, `Replies`, `Quotes`, `Views`, and `Bookmarks`.
  </Card>

  <Card title="Tweet metadata" icon="braces">
    `Language`, `Source`, and `Conversation ID`.
  </Card>

  <Card title="Article metadata" icon="file-text">
    `Article Title`, `Article Preview`, and `Article Body`.
  </Card>
</CardGroup>

### Article extractor columns

`article_extractor` uses a shorter column set for articles.

<CardGroup cols={2}>
  <Card title="Article identity" icon="file-text">
    `Article Title`, `Cover Image`, and `Article Body`.
  </Card>

  <Card title="Author identity" icon="user">
    `Author`, `Username`, and `Verified`.
  </Card>

  <Card title="Author reach" icon="chart-no-axes-column">
    `Followers`.
  </Card>

  <Card title="Article engagement" icon="activity">
    `Views`, `Likes`, and `Quotes`.
  </Card>
</CardGroup>

## Response

<Tabs>
  <Tab title="200 OK">
    Returns a file download. The response includes a `Content-Disposition` header with the filename.

    <CardGroup cols={2}>
      <Card title="CSV" icon="table">
        `format=csv` returns `text/csv; charset=utf-8` with filenames like
        `extraction-reply_extractor-*.csv`.
      </Card>

      <Card title="JSON" icon="braces">
        `format=json` returns `application/json; charset=utf-8` with filenames
        like `extraction-reply_extractor-*.json`. Each row adds the result's
        nested `enrichmentData` to its columns.
      </Card>

      <Card title="Markdown" icon="file-text">
        `format=md` returns `text/markdown; charset=utf-8` with filenames like
        `extraction-reply_extractor-*.md`.
      </Card>

      <Card title="Markdown document" icon="file-text">
        `format=md-document` returns `text/markdown; charset=utf-8` with
        filenames like `extraction-reply_extractor-*.md`.
      </Card>

      <Card title="PDF" icon="file-down">
        `format=pdf` returns `application/pdf` with filenames like
        `extraction-reply_extractor-*.pdf`.
      </Card>

      <Card title="TXT" icon="file">
        `format=txt` returns `text/plain; charset=utf-8` with filenames like
        `extraction-reply_extractor-*.txt`.
      </Card>

      <Card title="XLSX" icon="file-spreadsheet">
        `format=xlsx` returns
        `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
        with filenames like `extraction-reply_extractor-*.xlsx`.
      </Card>
    </CardGroup>

    Exports stop at 100,000 rows (10,000 for PDF). For extractions with more results, the export includes the first 100,000 rows ordered by result ID.
  </Tab>

  <Tab title="400 Invalid format">
    ```json theme={null}
    {
      "error": "invalid_format",
      "validFormats": ["csv", "json", "md", "md-document", "pdf", "txt", "xlsx"]
    }
    ```

    The `format` query parameter is missing or not one of the supported values.
  </Tab>

  <Tab title="401 Unauthenticated">
    ```json theme={null}
    { "error": "unauthenticated" }
    ```

    Missing or invalid API key.
  </Tab>

  <Tab title="404 Not found">
    ```json theme={null}
    { "error": "not_found" }
    ```

    No extraction job exists with this ID, or it belongs to a different account.
  </Tab>

  <Tab title="429 Rate limited">
    ```json theme={null}
    { "error": "rate_limit_exceeded", "message": "Too many requests. Try again later.", "retryAfter": 1 }
    ```

    Wait for the `Retry-After` value before requesting another export.
  </Tab>
</Tabs>

<Note>
  **Next steps.** [Get Extraction](/api-reference/extractions/twitter-extraction-results) to page through results with the API, or [List Extractions](/api-reference/extractions/twitter-scraping-job-history) to find other extraction jobs to export.
</Note>


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