SpyBara
Go Premium

tools/x-search.md 2026-09-28 23:57 UTC to 2026-09-29 23:59 UTC

This page contains 3 additions and 3 deletions.

2026
Tue 8 21:00 Mon 21 23:00 Tue 22 23:58 Tue 29 23:59

Tools

X Search

The X Search tool enables Grok to perform keyword search, semantic search, user search, and thread fetch on X (formerly Twitter). This powerful tool allows the model to access real-time social media content, analyze posts, and gather insights from X's vast data.

X Search is billed at $5 per 1k posts fetched and $10 per 1k user profiles fetched, in addition to token costs; see tool invocation costs for what counts as a fetched post or profile.

SDK Support

SDK/API Tool Name
xAI SDK x_search
OpenAI Responses API x_search
Vercel AI SDK xai.tools.xSearch()

This tool is also supported in all Responses API compatible SDKs.

Basic Usage

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4.7",  # reasoning model
    tools=[x_search()],
    include=["verbose_streaming"],
)

chat.append(user("What are people saying about xAI on X?"))

is_thinking = True
for response, chunk in chat.stream():
    for tool_call in chunk.tool_calls:
        print(f"\\nCalling tool: {tool_call.function.name} with arguments: {tool_call.function.arguments}")
    if response.usage.reasoning_tokens and is_thinking:
        print(f"\\rThinking... ({response.usage.reasoning_tokens} tokens)", end="", flush=True)
    if chunk.content and is_thinking:
        print("\\n\\nFinal Response:")
        is_thinking = False
    if chunk.content and not is_thinking:
        print(chunk.content, end="", flush=True)

print("\\n\\nCitations:")
print(response.citations)
import os
from openai import OpenAI

api_key = os.getenv("XAI_API_KEY")
client = OpenAI(
    api_key=api_key,
    base_url="https://api.x.ai/v1",
)

response = client.responses.create(
    model="grok-4.7",
    input=[
        {
            "role": "user",
            "content": "What are people saying about xAI on X?",
        },
    ],
    tools=[
        {
            "type": "x_search",
        },
    ],
)

print(response)
import { xai } from '@ai-sdk/xai';
import { generateText } from 'ai';

const { text, sources } = await generateText({
  model: xai.responses('grok-4.7'),
  prompt: 'What are people saying about xAI on X?',
  tools: {
    x_search: xai.tools.xSearch(),
  },
});

console.log(text);
console.log('Citations:', sources);
curl https://api.x.ai/v1/responses \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
  "model": "grok-4.7",
  "input": [
    {
      "role": "user",
      "content": "What are people saying about xAI on X?"
    }
  ],
  "tools": [
    {
      "type": "x_search"
    }
  ]
}'

X Search Parameters

Parameter Description
allowed_x_handles Only consider posts from specific X handles (max 20)
excluded_x_handles Exclude posts from specific X handles (max 20)
from_date Start date for search range (YYYY-MM-DD date only)
to_date End date for search range (YYYY-MM-DD date only)
enable_image_understanding Enable analysis of images in posts
enable_video_understanding Enable analysis of videos in posts

Only Consider Posts from Specific Handles

Use allowed_x_handles to consider X posts only from a given list of X handles. The maximum number of handles you can include is 20.

[!NOTE]

allowed_x_handles cannot be set together with excluded_x_handles in the same request.

import os

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4.7",
    tools=[
        x_search(allowed_x_handles=["elonmusk"]),
    ],
)

chat.append(user("What is the current status of xAI?"))
# stream or sample the response...
response = client.responses.create(
    model="grok-4.7",
    input=[{"role": "user", "content": "What is the current status of xAI?"}],
    tools=[
        {
            "type": "x_search",
            "allowed_x_handles": ["elonmusk"],
        },
    ],
)
const { text } = await generateText({
  model: xai.responses('grok-4.7'),
  prompt: 'What is the current status of xAI?',
  tools: {
    x_search: xai.tools.xSearch({
      allowedXHandles: ['elonmusk'],
    }),
  },
});

Exclude Posts from Specific Handles

Use excluded_x_handles to prevent the model from including X posts from the specified handles in any X search tool invocations. The maximum number of handles you can exclude is 20.

chat = client.chat.create(
    model="grok-4.7",
    tools=[
        x_search(excluded_x_handles=["elonmusk"]),
    ],
)
response = client.responses.create(
    model="grok-4.7",
    input=[{"role": "user", "content": "What is the current status of xAI?"}],
    tools=[
        {
            "type": "x_search",
            "excluded_x_handles": ["elonmusk"],
        },
    ],
)
const { text } = await generateText({
  model: xai.responses('grok-4.7'),
  prompt: 'What is the current status of xAI?',
  tools: {
    x_search: xai.tools.xSearch({
      excludedXHandles: ['elonmusk'],
    }),
  },
});

Date Range

You can restrict the date range of search data used by specifying from_date and to_date. This limits the data to the period from from_date to to_date, including both dates.

Use YYYY-MM-DD for both fields, e.g., "2025-10-01". Dates in any other format, including full date-times, aren't applied. If you're using the SpaceXAI Python SDK, you can pass from_date and to_date as datetime.datetime objects, but only the date (UTC) is used.

import os
from datetime import datetime

from xai_sdk import Client
from xai_sdk.chat import user
from xai_sdk.tools import x_search

client = Client(api_key=os.getenv("XAI_API_KEY"))
chat = client.chat.create(
    model="grok-4.7",
    tools=[
        x_search(
            from_date=datetime(2025, 10, 1),
            to_date=datetime(2025, 10, 10),
        ),
    ],
)

chat.append(user("What is the current status of xAI?"))
# stream or sample the response...
response = client.responses.create(
    model="grok-4.7",
    input=[{"role": "user", "content": "What is the current status of xAI?"}],
    tools=[
        {
            "type": "x_search",
            "from_date": "2025-10-01",
            "to_date": "2025-10-10",
        },
    ],
)
const { text } = await generateText({
  model: xai.responses('grok-4.7'),
  prompt: 'What is the current status of xAI?',
  tools: {
    x_search: xai.tools.xSearch({
      fromDate: '2025-10-01',
      toDate: '2025-10-10',
    }),
  },
});

Enable Image Understanding

Setting enable_image_understanding to true allows the agent to analyze images in X posts encountered during the search process.

chat = client.chat.create(
    model="grok-4.7",
    tools=[
        x_search(enable_image_understanding=True),
    ],
)
response = client.responses.create(
    model="grok-4.7",
    input=[{"role": "user", "content": "Find X posts with images about AI"}],
    tools=[
        {
            "type": "x_search",
            "enable_image_understanding": True,
        },
    ],
)
const { text } = await generateText({
  model: xai.responses('grok-4.7'),
  prompt: 'Find X posts with images about AI',
  tools: {
    x_search: xai.tools.xSearch({
      enableImageUnderstanding: true,
    }),
  },
});

Enable Video Understanding

Setting enable_video_understanding to true allows the agent to analyze videos in X posts. This is only available for X Search (not Web Search).

chat = client.chat.create(
    model="grok-4.7",
    tools=[
        x_search(enable_video_understanding=True),
    ],
)
response = client.responses.create(
    model="grok-4.7",
    input=[{"role": "user", "content": "Find X posts with videos about AI"}],
    tools=[
        {
            "type": "x_search",
            "enable_video_understanding": True,
        },
    ],
)
const { text } = await generateText({
  model: xai.responses('grok-4.7'),
  prompt: 'Find X posts with videos about AI',
  tools: {
    x_search: xai.tools.xSearch({
      enableVideoUnderstanding: true,
    }),
  },
});

Usage counts

Each Responses API response that ran X Search reports how many items it fetched, so you can reconcile a request against the per-item pricing in effect as of September 21, 2026. The counts live under usage.server_side_tool_usage_details, next to the per-call x_search_calls:

Field Counts
x_posts_fetched Posts returned by x_keyword_search, x_semantic_search, and x_thread_fetch, including parent and quoted posts and every post of a fetched thread
x_users_fetched User profiles returned by x_user_search

Both counts accumulate over every X Search call in the request and are not de-duplicated; a post returned by two searches counts twice. When streaming, the usage on the terminal event (response.completed, or response.incomplete when the response was truncated) is the total for the request.

The server_side_tool_usage_details block of a /v1/responses usage object after two X searches looks like this:

"server_side_tool_usage_details": {
  "web_search_calls": 0,
  "x_search_calls": 2,
  "x_posts_fetched": 44,
  "x_users_fetched": 3,
  "code_interpreter_calls": 0,
  "file_search_calls": 0,
  "mcp_calls": 0,
  "document_search_calls": 0,
  "image_generation_calls": 0
}

Citations

For details on how to retrieve and use citations from search results, see the Citations page.