PacketStream documentation

Parameters and request types

Every PacketStream Search API request field, the Google surface each request type searches, the options each type accepts, and batch searches.

Send the fields as a JSON body with POST /v1/search, or as query parameters with GET /v1/search. Only query is required.

curl -s https://api.packetstream.io/v1/search \
  -H "Authorization: Bearer $PACKETSTREAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "espresso machines", "type": "shopping", "country": "gb", "page": 2}'

The same search as a GET:

curl -s -G https://api.packetstream.io/v1/search \
  -H "Authorization: Bearer $PACKETSTREAM_API_KEY" \
  --data-urlencode "query=espresso machines" \
  --data-urlencode "type=shopping" \
  --data-urlencode "country=gb" \
  --data-urlencode "page=2"

Request fields

FieldTypeDefaultDescription
querystringrequiredThe search text. Google operators such as site: pass through. 1 to 400 bytes after trimming, or 1 to 200 bytes for autocomplete.
typestringsearchWhat to search: web results, news, shopping, and so on. One of the request types, case-insensitive.
countrystringusThe country to search from. Two-letter ISO 3166-1 code, case-insensitive.
languagestringnoneGoogle interface language. Up to 10 bytes, such as en, de, or pt-BR.
locationstringnoneCanonical Google location name, such as Austin,Texas,United States. 1 to 200 bytes. Cannot be combined with uule.
uulestringnoneEncoded Google location token. Up to 512 bytes. Cannot be combined with location. Never echoed in responses.
pageinteger1Result page. 1 to 10.
devicestringdesktopDevice to search as. desktop or mobile. Mobile results usually carry fewer rich blocks.
time_rangestringnoneOnly return results from this recent period. hour, day, week, month, or year.
safe_searchbooleanfalsetrue filters explicit results.
google_domainstringnoneGoogle domain to search, such as google.co.uk. Up to 32 bytes, case-insensitive.
autocorrectbooleantruefalse searches the query exactly as written.
formatstringjsonResponse format. json or markdown. Errors are always JSON. See Markdown format.

Validation rules:

  • Unknown, repeated, and mistyped fields return 400 invalid_request. The message names the field, for example unknown request field "engine".
  • A JSON null counts as an omitted field.
  • In a GET, booleans are true or false, integers are plain decimal digits, and each parameter may appear once.
  • A POST body may be at most 4,096 bytes, and so may a GET query string.

Request types

Each type accepts only the options listed. Any other option returns 400 unsupported_option before any charge, for example device is not supported for type news. Sending an option’s default value, such as "device": "desktop" or "page": 1, is always accepted. format works with every type, and every type costs the same.

TypeReturnsOptions
searchGoogle web results in results, plus rich blocks when Google shows them.Every option
newsGoogle News articles.country, language, page
shoppingGoogle Shopping offers.country, language, page
placesGoogle Maps places.country, language
autocompleteGoogle query suggestions.country, language
scholarGoogle Scholar publications.language, page
ai_modeA Google AI Mode answer in ai_mode, with its references. No results list.country, language

The API never drops an option silently. If no search source can serve a supported combination at the moment, the request fails with 400 unsupported_option and is not billed.

Responses lists the fields each type returns.

Batch searches

POST /v1/search/batch runs 1 to 10 searches in one request:

curl -s https://api.packetstream.io/v1/search/batch \
  -H "Authorization: Bearer $PACKETSTREAM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"searches": [
        {"query": "coffee grinders"},
        {"query": "coffee grinders", "type": "shopping"},
        {"query": "coffee grinders", "type": "news", "device": "mobile"}
      ]}'

The body is one JSON object whose only field is searches, an array of 1 to 10 items. Each item takes the request fields, and its format can only be json. The body may be at most 16 KiB.

The response lists one entry per item, in request order. Each entry has the item’s index, the HTTP status the item would have received on its own, and either the full search response or an error. In this shape, … stands for the left-out search fields:

{
  "request_id": "0b8f6c3e-5a2d-4c71-9e40-7d1f2a6b9c58",
  "results": [
    { "index": 0, "status": 200, "request_id": "0b8f6c3e-…", "search": {…}, "results": […], "charged_units": 1, … },
    { "index": 1, "status": 200, "request_id": "0b8f6c3e-…", "search": {…}, "results": […], "charged_units": 1, … },
    { "index": 2, "status": 400, "error": { "code": "unsupported_option", "message": "device is not supported for type news" } }
  ],
  "charged_units": 2
}
  • A valid batch returns HTTP 200 even when some items fail, so check each entry’s status.
  • Each item is a separate search. It is validated, rate-limited, checked against your balance, billed, and logged like a single search. The top-level charged_units counts the successful items.
  • Entries share the batch request_id. The request ID and index together identify an item.
  • Items are admitted in order, so when the rate limit or your balance runs out, later items fail first. A 10-item batch uses the key’s whole burst of 10.
  • Items run at the same time and share one 25-second deadline.
  • A malformed body, such as one without searches or with more than 10 items, returns 400 invalid_request for the whole request.
Questions? We’re here to help. Talk with our support team about your integration.
Contact support