Content

Search + Content

Search the web and get the full text of the top pages in one call.

Open in…
Ask on Discord
What your agent reads
`POST https://api.keirolabs.cloud/api/v2/search/content`

Cost: 1.5 credits paid · 3 free · Latency: ~3 s

Execute a search and scrape clean, markdown-formatted text from the top results in a single, unified call. The perfect foundation for RAG pipelines, LLM summarization, and AI agents. Returns enriched content with TLDR, tags, entities, and optional vector embeddings.

**When to use it.** Use Search+Content when you need the actual page text (markdown) for RAG, summarization, or AI agents. Returns clean content + TLDR + tags + optional embeddings in a single call.

**When not to.** Don't use if you only need URLs (use Search — cheaper), or if you need an LLM-synthesized answer (use Answer).

## Request

**cURL**

```bash
curl -X POST https://api.keirolabs.cloud/api/v2/search/content \
  -H "Authorization: Bearer $KEIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "how to reverse a linked list in python", "maxResults": 4, "mode": "medium"}'
```

**Python**

```python
import os, requests

res = requests.post(
    "https://api.keirolabs.cloud/api/v2/search/content",
    headers={"Authorization": f"Bearer {os.environ['KEIRO_API_KEY']}"},
    json={
        "query": "how to reverse a linked list in python",
        "maxResults": 4,
        "mode": "medium"
    },
)
print(res.json())
```

**Node.js**

```js
const res = await fetch("https://api.keirolabs.cloud/api/v2/search/content", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KEIRO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "query": "how to reverse a linked list in python",
    "maxResults": 4,
    "mode": "medium"
  }),
});
console.log(await res.json());
```

## Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `query` | string | yes | The search query (1-500 chars). |
| `maxResults` | integer | no | Number of pages to scrape. Default: 3. Max: 5 (server-clamped). |
| `mode` | enum | no | Extraction depth/method. Options: "medium" (full extraction + RAG enrichment, default), "deep" (renders JavaScript-heavy sites). |
| `objective` | string | no | Semantic objective extracts only text relevant to this goal, trimming noise from the page. |
| `country` | string | no | ISO-3166-1 alpha-2 country code to bias results. (Alias: location.) |
| `max_chars_source` | integer | no | Max characters extracted per source. Range: 1,000-10,000. Default: 7,000. |
| `max_chars_total` | integer | no | Max total characters across all sources. Range: 5,000-50,000. Default: 30,000. |
| `embeddings.enabled` | boolean | no | Generate vector embeddings for each content chunk. Default: false. Only honored in medium or deep mode. |
| `embeddings.dimensions` | integer | no | Matryoshka dimension truncation. Options: 384, 512, 768, 1024. Default: 768. |
| `embeddings.chunkSize` | integer | no | Characters per chunk for embedding. Range: 1500-2000. Default: 1500. Values outside this range are clamped. |

## Response

```json title="200 OK"
{
  "query": "how to reverse a linked list in python",
  "results": [
    {
      "title": "Reverse a Linked List - GeeksforGeeks",
      "url": "https://www.geeksforgeeks.org/python/reverse-a-linked-list/",
      "snippet": "Step-by-step guide with iterative and recursive solutions.",
      "content": "Reverse a Linked List\nGiven the head of a linked list, the iterative approach uses three pointers...",
      "metadata": {
        "word_count": 1200
      },
      "enrichment": {
        "tldr": "Reverse a linked list by flipping next-pointers iteratively in O(n) time and O(1) space.",
        "tags": [
          "python",
          "linked-list",
          "algorithms"
        ],
        "entities": {
          "key_entities": [
            "pointer",
            "head",
            "next"
          ]
        }
      },
      "embeddings": {
        "model": "baai/bge-m3",
        "dimensions": 768,
        "chunkSize": 1500,
        "chunkCount": 3,
        "totalChunks": 3,
        "chunks": [
          {
            "index": 0,
            "embedding": [
              0.0123,
              -0.0456,
              0.0789,
              "..."
            ]
          },
          {
            "index": 1,
            "embedding": [
              0.0234,
              -0.0567,
              0.089,
              "..."
            ]
          },
          {
            "index": 2,
            "embedding": [
              0.0345,
              -0.0678,
              0.0901,
              "..."
            ]
          }
        ],
        "truncated": false,
        "error": null
      },
      "error": ""
    }
  ],
  "count": 3,
  "latencyMs": 2706,
  "creditsCharged": 1.5,
  "creditsRemaining": 1138.5
}
```

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `results` | array | no | List of search results with extracted content. |
| `results[].title` | string | no | Page title. |
| `results[].url` | string | no | Full URL of the page. |
| `results[].content` | string | no | Clean markdown-formatted page content (main text, no nav/ads). |
| `results[].enrichment` | object | no | RAG enrichment: TLDR summary, tags, and named entities. |
| `results[].enrichment.tldr` | string | no | Auto-generated one-line summary of the page. |
| `results[].enrichment.tags` | array | no | Topic tags extracted from the content. |
| `results[].embeddings` | object | no | Vector embeddings (only if embeddings.enabled=true). |
| `results[].embeddings.chunks` | array | no | Array of { index, embedding } objects, one per chunk. |
| `results[].error` | string | no | Empty string if extraction succeeded; error message if it failed. |
| `creditsCharged` | number | no | Credits deducted (1.5 for paid tiers, 3 for free). |
| `creditsRemaining` | number | no | Your remaining credit balance. |

## Errors

| Status | Code | Cause | Fix |
| --- | --- | --- | --- |
| `400` | `VALIDATION_ERROR` | Missing query or invalid mode | Ensure query is provided and mode is "medium" or "deep". |
| `401` | `UNAUTHORIZED` | Missing or invalid API key | Check your Authorization: Bearer header. |
| `402` | `INSUFFICIENT_CREDITS` | Not enough credits | Buy more credits or upgrade your plan. |
| `429` | `RATE_LIMIT_EXCEEDED` | Too many requests | Check X-RateLimit-Remaining header. Wait for Retry-After seconds. |
| `502` | `SEARCH_UNAVAILABLE` | Extraction or search failure | Credits auto-refunded. Retry or try mode="medium" instead of "deep". |

## Rate limits

| Tier | Limit |
| --- | --- |
| Free | 10/min |
| Starter | 20/min |
| Pro | 40/min |
| Startup | 80/min |
| Enterprise | 120/min |

Over the limit you get a `429`. See [Rate limits](/rate-limits) for headers and backoff.
Every page: append .md to the URL. Whole site: /llms.txt · /llms-full.txt
POSThttps://api.keirolabs.cloud/api/v2/search/content
1.5 credits paid · 3 free~3 sTry it in the playground

Execute a search and scrape clean, markdown-formatted text from the top results in a single, unified call. The perfect foundation for RAG pipelines, LLM summarization, and AI agents. Returns enriched content with TLDR, tags, entities, and optional vector embeddings.

When to use it. Use Search+Content when you need the actual page text (markdown) for RAG, summarization, or AI agents. Returns clean content + TLDR + tags + optional embeddings in a single call.

When not to. Don't use if you only need URLs (use Search — cheaper), or if you need an LLM-synthesized answer (use Answer).

Request

curl -X POST https://api.keirolabs.cloud/api/v2/search/content \
  -H "Authorization: Bearer $KEIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "how to reverse a linked list in python", "maxResults": 4, "mode": "medium"}'

Parameters

Prop

Type

Response

200 OK
{
  "query": "how to reverse a linked list in python",
  "results": [
    {
      "title": "Reverse a Linked List - GeeksforGeeks",
      "url": "https://www.geeksforgeeks.org/python/reverse-a-linked-list/",
      "snippet": "Step-by-step guide with iterative and recursive solutions.",
      "content": "Reverse a Linked List\nGiven the head of a linked list, the iterative approach uses three pointers...",
      "metadata": {
        "word_count": 1200
      },
      "enrichment": {
        "tldr": "Reverse a linked list by flipping next-pointers iteratively in O(n) time and O(1) space.",
        "tags": [
          "python",
          "linked-list",
          "algorithms"
        ],
        "entities": {
          "key_entities": [
            "pointer",
            "head",
            "next"
          ]
        }
      },
      "embeddings": {
        "model": "baai/bge-m3",
        "dimensions": 768,
        "chunkSize": 1500,
        "chunkCount": 3,
        "totalChunks": 3,
        "chunks": [
          {
            "index": 0,
            "embedding": [
              0.0123,
              -0.0456,
              0.0789,
              "..."
            ]
          },
          {
            "index": 1,
            "embedding": [
              0.0234,
              -0.0567,
              0.089,
              "..."
            ]
          },
          {
            "index": 2,
            "embedding": [
              0.0345,
              -0.0678,
              0.0901,
              "..."
            ]
          }
        ],
        "truncated": false,
        "error": null
      },
      "error": ""
    }
  ],
  "count": 3,
  "latencyMs": 2706,
  "creditsCharged": 1.5,
  "creditsRemaining": 1138.5
}

Prop

Type

Errors

StatusCodeCauseFix
400VALIDATION_ERRORMissing query or invalid modeEnsure query is provided and mode is "medium" or "deep".
401UNAUTHORIZEDMissing or invalid API keyCheck your Authorization: Bearer header.
402INSUFFICIENT_CREDITSNot enough creditsBuy more credits or upgrade your plan.
429RATE_LIMIT_EXCEEDEDToo many requestsCheck X-RateLimit-Remaining header. Wait for Retry-After seconds.
502SEARCH_UNAVAILABLEExtraction or search failureCredits auto-refunded. Retry or try mode="medium" instead of "deep".

Rate limits

TierLimit
Free10/min
Starter20/min
Pro40/min
Startup80/min
Enterprise120/min

Over the limit you get a 429. See Rate limits for headers and backoff.

Let your agent build it

Paste one prompt into Claude Code, Cursor, Codex or Windsurf. It installs Keiro MCP, reads these docs and writes the integration against the real API.

Ask on Discord

On this page