Product review · from official docs

PacketStream Search API, Fetch API & MCP server

Three pay-per-success APIs on the same prepaid balance as the proxies: Google results, pages as Markdown, and an MCP server that gives AI agents both. Here is what they do, what they cost and how to set them up.

Updated October 2026 [VERIFIED 2026-10-17] by the packetstream-reviews.com editorial desk

On this page

Overview

Base URL
https://api.packetstream.io
Search API
GET/POST /v1/search · Google results
Fetch API
POST /v1/fetch · page → Markdown
MCP server
POST /v1/mcp · Streamable HTTP
Price
$0.0025 per successful call ($2.50/1,000) [VERIFIED 2026-10-17]
Failed calls
Free (rare 500 exception)
Balance
Same prepaid balance as proxies; never expires
Auth
Authorization: Bearer ps_… (one key for all three)
Rate limit
5 req/s per key, bursts to 10 (shared)

This page describes what PacketStream documents — and the docs are unusually precise about limits and error semantics — plus how the prices compare.

API key & authentication

Create the key on the Search API or MCP page of the PacketStream dashboard. It is shown once. Keys start with ps_ followed by 64 hexadecimal characters; an account has one active key, used by Search, Fetch and MCP. Rotating it revokes the old key immediately. The API sends no CORS headers, so it cannot be called from a web page — keep the key on a server or in your agent’s config.

The docs load the key without writing it into shell history:

shell bash
read -r -s -p 'PacketStream API key: ' PACKETSTREAM_API_KEY
printf '\n'
export PACKETSTREAM_API_KEY
Source: Search API, PacketStream docs, checked 17 Oct 2026.

Check the key and balance for free (this call does not use a rate-limit token):

account-check.sh bash
curl -sS https://api.packetstream.io/v1/account \
  -H "Authorization: Bearer $PACKETSTREAM_API_KEY"
Source: MCP overview, PacketStream docs, checked 17 Oct 2026.

Fetch API

POST /v1/fetch reads one public page live through the residential network and returns its main content as Markdown, with the final URL, HTTP status, title and description. It accepts POST only, so URLs stay out of query strings.

fetch.sh bash
curl -s https://api.packetstream.io/v1/fetch \
  -H "Authorization: Bearer $PACKETSTREAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://go.dev/doc/effective_go", "max_length": 20000}'
Source: Fetch API, PacketStream docs, checked 17 Oct 2026.
fetch.py python
import os
import requests

response = requests.post(
    "https://api.packetstream.io/v1/fetch",
    headers={"Authorization": f"Bearer {os.environ['PACKETSTREAM_API_KEY']}"},
    json={"url": "https://go.dev/doc/effective_go", "max_length": 20000},
    timeout=35,
)
response.raise_for_status()
page = response.json()["page"]
print(page["title"], page["final_url"])
print(page["content"])
if page["truncated"]:
    print("Continue with start_index", page["next_start_index"])
Source: Fetch API, PacketStream docs, checked 17 Oct 2026.
fetch.mjs javascript
const response = await fetch("https://api.packetstream.io/v1/fetch", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PACKETSTREAM_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://go.dev/doc/effective_go" }),
  signal: AbortSignal.timeout(35_000),
});
const payload = await response.json();
if (!response.ok) throw new Error(`${payload.error.code}: ${payload.error.message}`);
console.log(payload.page.title, payload.page.content);
Run server-side only, so the key stays private. Source: Fetch API, PacketStream docs, checked 17 Oct 2026.

The documented response for the curl example, with the page text shortened:

response.json json
{
  "request_id": "0b9e6c1d-2f4a-4b8c-9d3e-5f6a7b8c9d0e",
  "fetch": {
    "url": "https://go.dev/doc/effective_go",
    "content": "main",
    "include_links": true,
    "country": "us"
  },
  "page": {
    "final_url": "https://go.dev/doc/effective_go",
    "status_code": 200,
    "title": "Effective Go - The Go Programming Language",
    "description": "",
    "content_type": "text/markdown",
    "source_content_type": "text/html",
    "fetched_at": "2026-10-07T12:00:00Z",
    "content": "# Effective Go\n\n## Introduction\n\nGo is a new language. …",
    "start_index": 0,
    "returned_length": 20000,
    "total_length": 104112,
    "truncated": true,
    "next_start_index": 20000,
    "source_truncated": false
  },
  "charged_units": 1,
  "balance_remaining_usd": 12.3475,
  "processing_time_ms": 910
}
Source: Fetch API, PacketStream docs, checked 17 Oct 2026.

Request fields

url
required · public http/https, ports 80/443, ≤ 2,048 bytes
content
main (default, readability extraction) or full
include_links
true (default); false drops images and link URLs
max_length
50,000 default · 1–500,000 characters
start_index
0 default · for reading long pages in parts
country
us (default) · ISO code, e.g. gb not uk
user_agent
current desktop Chrome (default) · ≤ 512 chars

How it behaves

  • Content types. Fetch reads the HTML and text the server returns. Pages that need JavaScript return 422 javascript_required, and PDFs and images return unsupported_content_type; both are free.
  • Retries. One automatic retry after a network or connection failure.
  • Plain request. One GET over HTTP/1.1 with a browser-style Accept, Accept-Language: en-US, no cookies, no Referer.
  • Redirects. Follows 301/302/303/307/308 up to 5; a sixth returns too_many_redirects.
  • Public URLs only. IP addresses, internal hosts, URLs with credentials or containing an API key are refused.
  • Time. Server gives up after 25 seconds; set your client timeout to at least 35.
  • robots.txt. Fetch does not read it; you need whatever permission the law, a contract or the site operator requires.
  • Privacy. Records request ID, outcome, latency and charge — not the URL, user agent or page content.

Long pages: when page.truncated is true, send the same request with start_index set to page.next_start_index. Each part downloads the page again and is billed again. Billing: $0.0025 per fetch that returns content; every error is free, including the target’s own 4xx/5xx, timeouts and rate limits.

MCP server

The MCP server at https://api.packetstream.io/v1/mcp exposes two tools to AI agents. It uses the Streamable HTTP transport and is stateless: each POST gets one JSON response, with no event stream and no session. Authentication is an Authorization: Bearer header — no OAuth — so your client must let you set a custom header.

MCP tools (server version 1.3.0)
ToolDoesDiffers from RESTPrice
packetstream_search Google search; Markdown text plus JSON as structuredContent No format argument $0.0025
packetstream_fetch Reads a public page as Markdown Always US exit (no country); include_links false; max_length 40,000 (1,000–100,000) $0.0025
  • Listing tools, initialize and ping are free and need no key — so a client showing the server as “connected” has not checked your key. Use the free account check above.
  • Fetched text is wrapped in <<<PAGE CONTENT: untrusted>>> markers; agents should treat it as data, never instructions.
  • Tools were renamed from web_search/web_fetch in version 1.3.0; update any allow-lists that name the old tools.
Spend control

The server’s instructions ask agents to use these tools for every web search and page fetch, in place of their built-in web tools, so one agent task can make many billed calls. PacketStream’s docs say to review your client’s tool-approval settings to control spend. At $0.0025 a call, 1,000 calls is $2.50.

MCP client setup

Configs below are verbatim from PacketStream’s MCP client setup page. Replace YOUR_API_KEY with your key. PacketStream says it tested Claude Code 2.1.284, Codex CLI 0.159.0 and the mcp-remote 0.14.2 bridge against the live server on 7 October 2026; the Cursor, VS Code and Claude Desktop steps follow those vendors’ own docs.

Claude Code

terminal bash
export PACKETSTREAM_API_KEY="YOUR_API_KEY"
claude mcp add --transport http --scope user packetstream https://api.packetstream.io/v1/mcp \
  --header 'Authorization: Bearer ${PACKETSTREAM_API_KEY}'
claude mcp list
The single quotes store the variable name, not the key. Keep --header after the URL.

To share with a team, commit a .mcp.json at the repository root; each person sets their own variable:

.mcp.json json
{
  "mcpServers": {
    "packetstream": {
      "type": "http",
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer ${PACKETSTREAM_API_KEY}" }
    }
  }
}

Codex CLI

terminal bash
export PACKETSTREAM_API_KEY="YOUR_API_KEY"
codex mcp add packetstream --url https://api.packetstream.io/v1/mcp \
  --bearer-token-env-var PACKETSTREAM_API_KEY
~/.codex/config.toml toml
[mcp_servers.packetstream]
url = "https://api.packetstream.io/v1/mcp"
bearer_token_env_var = "PACKETSTREAM_API_KEY"
Codex refuses to start the server while the variable is unset. With approval_policy = "never", add default_tools_approval_mode = "approve" to this table or every call is refused (unbilled).

Cursor

~/.cursor/mcp.json json
{
  "mcpServers": {
    "packetstream": {
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
In a committed project file, use "Bearer ${env:PACKETSTREAM_API_KEY}" instead of the literal key.

VS Code

.vscode/mcp.json json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "packetstream-api-key",
      "description": "PacketStream API key",
      "password": true
    }
  ],
  "servers": {
    "packetstream": {
      "type": "http",
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer ${input:packetstream-api-key}" }
    }
  }
}
VS Code prompts for the key once and stores it securely.

Claude Desktop

claude_desktop_config.json json
{
  "mcpServers": {
    "packetstream": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.packetstream.io/v1/mcp",
        "--transport",
        "http-only",
        "--header",
        "Authorization:${PACKETSTREAM_AUTH_HEADER}"
      ],
      "env": { "PACKETSTREAM_AUTH_HEADER": "Bearer YOUR_API_KEY" }
    }
  }
}
Uses the community mcp-remote bridge (needs Node.js). No space after the colon in the header argument, on purpose.

Other clients

mcp config json
{
  "mcpServers": {
    "packetstream": {
      "type": "http",
      "url": "https://api.packetstream.io/v1/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
Choose Streamable HTTP, not SSE. Cline needs "type": "streamableHttp"; Gemini CLI needs httpUrl instead of url.

Clients that cannot send a custom header — ChatGPT on the web, and Claude custom connectors without Anthropic’s request-header beta — can list the tools but every call returns missing_api_key. Key errors (missing_api_key, invalid_api_key, unauthorized) are never billed.

Rate limits, errors & retries

Rate limit
5 req/s per key, bursts of 10 — Search, batch items, Fetch and MCP share it
Over the limit
429 rate_limited, Retry-After: 1
Fetch concurrency
4 per key per API server (429 concurrency_limited)
Per-site fetch limit
“a few” new fetches/s per domain, across all customers
Server timeout
25 s (client ≥ 35 s)
Request body
≤ 4,096 bytes (batch ≤ 16 KiB)
Minimum balance
$0.0025 before a call starts

The docs’ retry rules are sensible defaults: retry a 429 after Retry-After; retry a 503 with exponential backoff and jitter; retry a 500 at most once (it can rarely follow a successful charge — check your balance first if a duplicate matters); never retry a 400, 401, 402, 405 or 413 without changing something. If your client times out before the server’s 25 seconds, the search can still finish and be billed.

The per-site fetch limit is shared across all PacketStream customers. For fast crawls of a single domain, run your own crawler through the $1/GB proxies.

Pricing compared

Google SERP cost per 1,000 successful searches, list prices as of October 2026
ServicePer 1,000Billing model
PacketStream Search API$2.50Prepaid, never expires; no subscription; failures free
Bright Data SERP API$1.50Pay-as-you-go, success-only; 5K free records/month
Oxylabs Web API (Google)$1.00 → $0.50Subscription only
Apify Google SERP proxy$2.50 → $1.70Platform plans
ScraperAPI Hobby≈ $12.25Subscription; Google = 25 credits

The Search API costs about a fifth of ScraperAPI’s Hobby rate for Google and matches Apify’s entry SERP price, with no subscription. Searches come out of the same never-expiring balance as the proxies, failed calls are free, its terms describe no up-front ID check, and one MCP server covers search and fetch. Fetch costs the same $0.0025 per page that returns content, with clean Markdown out and every error free. Billing and SERP maths are worked through on the pricing page.

Strengths of the APIs

packetstream-apis.diff · +7

@@ strengths @@

  • Searches and fetches use the same never-expiring balance as the proxies; no subscription
  • Failed calls are free, including the target site’s own errors (rare 500 exception)
  • Seven Google result types, including AI Mode and Scholar
  • Clean Markdown output, with the final URL, status, title and description
  • One MCP server for search and fetch, with documented configs for five clients
  • No up-front ID check described in the terms
  • Precise docs on errors, billing edge cases and retries

If you already hold a PacketStream balance, the APIs are a low-commitment way to give an agent Google search and page reads: no plan, failed calls free, and the same balance as the proxies.