> ## 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 scraping cost estimator & credit quote

> Estimate API credits before exporting tweet searches, replies, followers, following, profiles, communities, or lists. The quote is free and starts no job.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-extractions-twitter-scraping-cost-estimator-200">
      ```json theme={null}
      {
        "allowed": true,
        "creditsAvailable": "50000",
        "creditsRequired": "500",
        "estimatedResults": 500,
        "source": "replyCount"
      }
      ```
    </Tab>

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

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

    <Tab title="402" id="response-extractions-twitter-scraping-cost-estimator-402">
      ```json theme={null}
      {
        "error": "insufficient_credits",
        "message": "Insufficient credits. Top up or subscribe to continue."
      }
      ```
    </Tab>

    <Tab title="403" id="response-extractions-twitter-scraping-cost-estimator-403">
      ```json theme={null}
      {
        "error": "x_account_protected",
        "message": "Account is protected. Choose a public account."
      }
      ```
    </Tab>

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

    <Tab title="429" id="response-extractions-twitter-scraping-cost-estimator-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 -X POST https://xquik.com/api/v1/extractions/estimate \
    -H "x-api-key: xq_YOUR_KEY_HERE" \
    -H "Content-Type: application/json" \
    -d '{
      "toolType": "reply_extractor",
      "targetTweetId": "1893704267862470862",
      "resultsLimit": 500
    }' | jq
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://xquik.com/api/v1/extractions/estimate", {
    method: "POST",
    headers: {
      "x-api-key": "xq_YOUR_KEY_HERE",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      toolType: "reply_extractor",
      targetTweetId: "1893704267862470862",
      resultsLimit: 500,
    }),
  });
  const data = await response.json();

  if (data.allowed) {
    // Safe to proceed with extraction
  }
  ```

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

  response = requests.post(
      "https://xquik.com/api/v1/extractions/estimate",
      headers={"x-api-key": "xq_YOUR_KEY_HERE"},
      json={
          "toolType": "reply_extractor",
          "targetTweetId": "1893704267862470862",
          "resultsLimit": 500,
      },
  )
  data = response.json()

  if data.get("allowed"):
      # Safe to proceed with extraction
      pass
  ```

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

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

  func main() {
      body, _ := json.Marshal(map[string]interface{}{
          "toolType":      "reply_extractor",
          "targetTweetId": "1893704267862470862",
          "resultsLimit":  500,
      })

      req, err := http.NewRequest("POST", "https://xquik.com/api/v1/extractions/estimate", bytes.NewReader(body))
      if err != nil {
          panic(err)
      }
      req.Header.Set("x-api-key", "xq_YOUR_KEY_HERE")
      req.Header.Set("Content-Type", "application/json")

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

      var data map[string]interface{}
      if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
          panic(err)
      }
      fmt.Println(data)
  }
  ```
</CodeGroup>

## Estimate Twitter API scraping cost

Request a free credit quote before starting any extraction. The response estimates results and required credits. It also checks your available credit balance. A quote never starts a scraping job.

Use the same request fields for estimation and extraction. Keep `toolType`, target fields, filters, and `resultsLimit` unchanged. The quote then matches the job you run.

### Match each scraping task

| Twitter scraping task | `toolType` | Required target | Estimated results |
| - | - | - | - |
| Search tweets with filters | `tweet_search_extractor` | `searchQuery` | Matching tweet search results |
| Export tweet replies | `reply_extractor` | `targetTweetId` | Replies beneath one tweet |
| Export followers | `follower_explorer` | `targetUsername` | Follower profiles |
| Export following | `following_explorer` | `targetUsername` | Followed profiles |
| Export profile tweets | `post_extractor` | `targetUsername` | Tweets from one profile |
| Export community tweets | `community_post_extractor` | `targetCommunityId` | Tweets from one community |
| Export list members | `list_member_extractor` | `targetListId` | Profiles inside one list |
| Export list tweets | `list_post_extractor` | `targetListId` | Tweets from list members |

Other supported tools estimate likes, media, mentions, quotes, reposts, threads, Spaces, and articles. Use their matching target fields below.

### Control the credit quote

`resultsLimit` defaults to `10,000`. Set any positive integer for a different bound. The estimator adjusts `creditsRequired` for that projected count.

Narrow tweet search estimates with dates, authors, languages, engagement thresholds, or media filters. Reuse those filters when creating the extraction. Changed filters can produce a different estimate.

Post estimates use the 1,000-row cap. A protected profile returns 403 `x_account_protected`.

### Read the estimate

When `allowed` is `false`, lower `resultsLimit`, narrow filters, or add credits. Then request another quote.

## Headers

<ParamField header="x-api-key" type="string" required>
  Your API key. Session cookie authentication is also supported. Generate a key from the [dashboard](https://xquik.com/dashboard).
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

The estimator accepts the same fields as Create Extraction.

## Body

<ParamField body="toolType" type="string" required>
  Extraction tool to run or estimate. See the endpoint's tool list.
</ParamField>

### Single targets

<ParamField body="targetTweetId" type="string">
  Tweet ID for a tweet-centered extraction.
</ParamField>

<ParamField body="targetUsername" type="string">
  Username for an account-centered extraction. You may include `@`.
</ParamField>

<ParamField body="targetCommunityId" type="string">
  Community ID for a community extraction.
</ParamField>

<ParamField body="targetListId" type="string">
  List ID for a list extraction.
</ParamField>

<ParamField body="targetSpaceId" type="string">
  Space ID for `space_explorer`.
</ParamField>

<ParamField body="searchQuery" type="string">
  Query for `tweet_search_extractor` or `community_search`.
</ParamField>

### Collection targets

<ParamField body="targetTweetIds" type="string[]">
  Process 1-10,000 Tweet IDs in one collection job.
</ParamField>

<ParamField body="targetUsernames" type="string[]">
  Process 1-100 unique usernames in one job. `tweet_search_extractor` collects their posts.
</ParamField>

<ParamField body="targetCommunityIds" type="string[]">
  Process 1-100 unique community IDs in one collection job.
</ParamField>

<ParamField body="targetListIds" type="string[]">
  Process 1-100 unique List IDs in one collection job.
</ParamField>

<ParamField body="searchQueries" type="string[]">
  Process 1-100 unique search queries in one collection job.
</ParamField>

<ParamField body="targets" type="array">
  Process up to 10,000 mixed targets with automatic routing.
</ParamField>

Each target accepts a supported string or `{ "kind": "...", "value": "..." }`.

<ParamField body="relationTargets" type="array">
  Process up to 100 profile relations in one collection job.
</ParamField>

Each relation target uses `{ "relation": "...", "value": "..." }`.

### Collection controls

<ParamField body="queryType" type="string">
  Search ranking: `Latest`, `Top`, or `Both`. Defaults to `Latest`.
</ParamField>

<ParamField body="resultsLimit" type="integer">
  Maximum unique results to emit. Defaults to `10,000`. Use any positive integer.
</ParamField>

<ParamField body="maxItemsPerTarget" type="integer">
  Maximum results collected for each target. Minimum: `1`.
</ParamField>

<ParamField body="maxPagesPerTarget" type="integer">
  Reply pages collected per target. Range: `1-1,000`.
</ParamField>

<ParamField body="startCursor" type="string">
  Resume one reply target from this cursor.
</ParamField>

<ParamField body="dedupeAcrossTargets" type="boolean">
  Merge duplicates across targets. Defaults to `true`.
</ParamField>

<ParamField body="dedupeMode" type="string">
  Duplicate handling: `none`, `first`, or `merge`.
</ParamField>

<ParamField body="overlapMode" type="boolean">
  Use `dedupeMode=merge`. Defaults to `false`.
</ParamField>

<ParamField body="includeSearchTerms" type="boolean">
  Add matched search terms to collection metadata. Defaults to `false`.
</ParamField>

<ParamField body="includeTargetMetadata" type="boolean">
  Add source target metadata to each result. Defaults to `true`.
</ParamField>

<ParamField body="enrichProfiles" type="boolean">
  Add each user's full profile at `enrichmentData.profile`. Applies to
  `follower_explorer`, `following_explorer`, `verified_follower_explorer`,
  `people_search` & `repost_extractor`. Jobs take longer. Defaults to `false`.
</ParamField>

### Reply collection

<ParamField body="collectionStrategy" type="string">
  Strategy: `auto`, `complete`, `direct`, `search`, or `thread`.
</ParamField>

<ParamField body="scope" type="string">
  Reply scope: `all`, `direct`, or `nested`. Defaults to `all`.
</ParamField>

<ParamField body="maxDepth" type="integer">
  Maximum nested reply depth. Minimum: `1`.
</ParamField>

<ParamField body="sort" type="string">
  Order: `relevance`, `latest`, `oldest`, or `likes`.
</ParamField>

<ParamField body="excludeOriginalAuthor" type="boolean">
  Exclude replies from the source author. Defaults to `false`.
</ParamField>

<ParamField body="includeOriginalPost" type="boolean">
  Include the source post. Defaults to `false`.
</ParamField>

<ParamField body="hasMediaOnly" type="boolean">
  Return only replies with media. Defaults to `false`.
</ParamField>

<ParamField body="sinceTime" type="string | integer">
  Reply start time as ISO 8601 or Unix seconds.
</ParamField>

<ParamField body="untilTime" type="string | integer">
  Reply end time as ISO 8601 or Unix seconds.
</ParamField>

### Tweet result filters

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

<ParamField body="minBookmarks" type="integer">
  Minimum Tweet bookmark count.
</ParamField>

<ParamField body="maxLikes" type="integer">
  Maximum Tweet like count.
</ParamField>

<ParamField body="maxRetweets" type="integer">
  Maximum Tweet repost count.
</ParamField>

<ParamField body="maxReplies" type="integer">
  Maximum Tweet reply count.
</ParamField>

<ParamField body="maxQuotes" type="integer">
  Maximum Tweet quote count.
</ParamField>

<ParamField body="blueVerifiedOnly" type="boolean">
  Return only Blue-verified Tweet authors. Defaults to `false`.
</ParamField>

<ParamField body="cardName" type="string">
  X search no longer supports `cardName`, so a search with it finds no Tweets.
</ParamField>

<ParamField body="source" type="string">
  X search no longer supports `source`, so a search with it finds no Tweets.
</ParamField>

<ParamField body="excludeSource" type="string">
  X search no longer supports `excludeSource`, so a search ignores it.
</ParamField>

<ParamField body="geocode" type="string">
  X search no longer supports `geocode`, so a search with it finds no Tweets.
</ParamField>

<ParamField body="sinceId" type="string">
  Return Tweets whose IDs exceed this ID.
</ParamField>

<ParamField body="maxId" type="string">
  Return Tweets at or below this ID.
</ParamField>

<ParamField body="near" type="string">
  Match a place name.
</ParamField>

<ParamField body="within" type="string">
  X search no longer supports `within`, so a search with it finds no Tweets. Use
  `near` alone.
</ParamField>

<ParamField body="withinTime" type="string">
  Match Tweets inside a recent time window.
</ParamField>

<ParamField body="nativeRetweets" type="boolean">
  Return only native reposts. Defaults to `false`.
</ParamField>

<ParamField body="safe" type="boolean">
  Enable safe search. Defaults to `false`.
</ParamField>

<ParamField body="news" type="boolean">
  X no longer searches `filter:news`, so leave this unset.
</ParamField>

### Profile result filters

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

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

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

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

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

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

<ParamField body="minAccountAgeDays" type="integer">
  Minimum profile age in days.
</ParamField>

<ParamField body="verifiedType" type="string">
  Match the exact profile verification type.
</ParamField>

<ParamField body="hasWebsite" type="boolean">
  Require a profile website. Defaults to `false`.
</ParamField>

<ParamField body="hasLocation" type="boolean">
  Require a profile location. Defaults to `false`.
</ParamField>

<ParamField body="bioContains" type="string">
  Require bio terms separated by commas or lines.
</ParamField>

<ParamField body="locationContains" type="string">
  Require matching profile location text.
</ParamField>

<ParamField body="usernameContains" type="string">
  Require matching username text.
</ParamField>

### Tweet search filters

These fields apply to `tweet_search_extractor`.

<ParamField body="fromUser" type="string">
  Match an author username without `@`.
</ParamField>

<ParamField body="toUser" type="string">
  Match replies sent to a username.
</ParamField>

<ParamField body="mentioning" type="string">
  Match Tweets mentioning a username.
</ParamField>

<ParamField body="language" type="string">
  Match a language code, such as `en`.
</ParamField>

<ParamField body="sinceDate" type="string">
  Include Tweets on or after `YYYY-MM-DD`.
</ParamField>

<ParamField body="untilDate" type="string">
  Include Tweets up to `YYYY-MM-DD`, a UTC day, inclusive, so its own Tweets count.
</ParamField>

<ParamField body="mediaType" type="string">
  Media: `images`, `videos`, `gifs`, `media`, `links`, or `none`.
</ParamField>

<ParamField body="minFaves" type="integer">
  Minimum like count.
</ParamField>

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

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

<ParamField body="minQuotes" type="integer">
  Minimum quote count.
</ParamField>

<ParamField body="verifiedOnly" type="boolean">
  Return only verified authors.
</ParamField>

<ParamField body="replies" type="string">
  Reply mode: `include`, `exclude`, or `only`.
</ParamField>

<ParamField body="retweets" type="string">
  Repost mode: `include`, `exclude`, or `only`.
</ParamField>

<ParamField body="quotes" type="string">
  Quote mode: `include`, `exclude`, or `only`.
</ParamField>

<ParamField body="exactPhrase" type="string">
  Match one exact phrase.
</ParamField>

<ParamField body="excludeWords" type="string">
  Exclude words or quoted phrases.
</ParamField>

<ParamField body="anyWords" type="string">
  Match any listed word or quoted phrase.
</ParamField>

<ParamField body="hashtags" type="string">
  Match hashtags separated by spaces, commas, or lines.
</ParamField>

<ParamField body="cashtags" type="string">
  Match cashtags separated by spaces, commas, or lines.
</ParamField>

<ParamField body="url" type="string">
  Match a URL substring or domain.
</ParamField>

<ParamField body="conversationId" type="string">
  Match a conversation ID.
</ParamField>

<ParamField body="inReplyToTweetId" type="string">
  Return only replies to this Tweet ID.
</ParamField>

<ParamField body="quotesOfTweetId" type="string">
  Return only quotes of this Tweet ID.
</ParamField>

<ParamField body="retweetsOfTweetId" type="string">
  Return only reposts of this Tweet ID.
</ParamField>

<ParamField body="listId" type="string">
  Search within a List ID.
</ParamField>

<ParamField body="place" type="string">
  Search within a place ID.
</ParamField>

<ParamField body="placeCountry" type="string">
  Search within a country code.
</ParamField>

<ParamField body="pointRadius" type="string">
  Set a geographic center and radius.
</ParamField>

<ParamField body="boundingBox" type="string">
  Set a geographic bounding box.
</ParamField>

<ParamField body="advancedQuery" type="string">
  Append raw advanced search syntax.
</ParamField>

## Response

### 200 OK

<ResponseField name="allowed" type="boolean">
  Whether the extraction can proceed given the current credit balance.
</ResponseField>

<ResponseField name="source" type="string">
  Data source used for the estimate. One of: `collection`, `followers`, `following`,
  `paginationCap`, `quoteCount`, `replyCount`, `resultsLimit`, `retweetCount`, `unknown`.
</ResponseField>

<ResponseField name="estimatedResults" type="number">
  Estimated number of results the extraction will return.
</ResponseField>

<ResponseField name="creditsRequired" type="string">
  Credits this extraction will consume (stringified integer).
</ResponseField>

<ResponseField name="creditsAvailable" type="string">
  Credits available in your balance (stringified integer).
</ResponseField>

<ResponseField name="resolvedXUserId" type="string">
  Resolved X user ID from count-based profile estimates.
</ResponseField>

```json theme={null}
{
  "allowed": true,
  "creditsRequired": "500",
  "creditsAvailable": "50000",
  "estimatedResults": 250,
  "source": "replyCount",
  "resolvedXUserId": "123456"
}
```

When `allowed` is `false`, credits required exceed the available balance:

```json theme={null}
{
  "allowed": false,
  "creditsRequired": "250000",
  "creditsAvailable": "18000",
  "estimatedResults": 250000,
  "source": "followers"
}
```

### 400 Invalid input

```json theme={null}
{ "error": "invalid_input" }
```

The request body is missing or malformed. Send `toolType` and its matching target field.

### 400 Invalid tool type

```json theme={null}
{ "error": "invalid_tool_type" }
```

The `toolType` value is not one of the 23 supported tools.

### 401 Unauthenticated

```json theme={null}
{ "error": "unauthenticated" }
```

Missing or invalid API key.

### 402 Insufficient credits

```json theme={null}
{ "error": "insufficient_credits" }
```

The available balance cannot cover the estimate. Possible error values include `no_subscription`, `subscription_inactive`, `no_credits`, and `insufficient_credits`.

### 404 Not found

```json theme={null}
{ "error": "tweet_not_found", "message": "Tweet not found" }
```

The target tweet does not exist, was deleted, or the ID is invalid.

```json theme={null}
{ "error": "user_not_found", "message": "X user not found" }
```

The target user does not exist or is suspended.

### 429 Rate limited

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Try again later.",
  "retryAfter": 60
}
```

Wait for the `Retry-After` value before requesting another estimate.

## Decision handoff

A `200 OK` response is a quote. It starts no extraction. Store the estimate with the request you plan to run:

```json theme={null}
{
  "checkpoint_type": "extraction_estimate",
  "toolType": "reply_extractor",
  "targetTweetId": "1893704267862470862",
  "resultsLimit": 500,
  "estimatedResults": 500,
  "creditsRequired": "500",
  "creditsAvailable": "50000",
  "allowed": true,
  "source": "replyCount",
  "next_action": "create_extraction",
  "create_path": "/api/v1/extractions",
  "fallback_action": "lower_results_limit_or_add_credits"
}
```

<CardGroup cols={2}>
  <Card title="Allowed run" icon="circle-check">
    When `allowed` is `true`, send the same `toolType`, target fields, filters, and `resultsLimit` to [Create Extraction](/api-reference/extractions/create). Store the returned job ID from that `202 Accepted` receipt.
  </Card>

  <Card title="Blocked run" icon="circle-alert">
    When `allowed` is `false`, lower `resultsLimit`, narrow the target or filters, or add credits before calling [Create Extraction](/api-reference/extractions/create).
  </Card>

  <Card title="Source signal" icon="gauge">
    Store `source` so operators know whether the estimate came from `replyCount`, `followers`, `resultsLimit`, `paginationCap`, or another supported count.
  </Card>

  <Card title="Audit fields" icon="clipboard-check">
    Store `estimatedResults`, `creditsRequired`, `creditsAvailable`, `allowed`, and `source` with the planned extraction request.
  </Card>
</CardGroup>

<Note>
  **Call this endpoint before every extraction.** It catches credit shortfalls before the job starts. If `allowed` is `false`, Create Extraction returns a `402` error. Check your current usage on the [dashboard](https://xquik.com/dashboard).
</Note>

<Note>
  **Next steps.** [Create Extraction](/api-reference/extractions/create) to start an extraction, or [Extraction Workflow Guide](/guides/extraction-workflow) for the full flow.
</Note>


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