Exposed search actions become a structured result with explicit evidence boundaries.

Extract OpenAI search queries from Responses: parser and edge cases

Read exposed strings from search actions of web_search_call items in Responses output. Keep their action membership and response status. The downloadable parser preserves exact strings without inventing queries or source relationships.

Use this when processing Responses JSON. All test responses are explicitly synthetic; this tutorial requires no paid call.

Inspect your own result nextThe offline kit needs no API key. You can later inspect a separate bounded run in the free tool.Open the free tool

Check the response before reading search actions

Begin at the request layer. An HTTP error or timeout is not a successful response containing zero queries. Pass received JSON to the parser; keep transport failures as separate states. The offline example makes no request and therefore contains no credentials.

The parser requires an output array and selects web_search_call actions whose type is search. It supports exposed queries and query fields. It counts open_page and find_in_page separately as web-tool calls, without treating them as search queries. It never fills a missing search string from the input or answer text.

Download and extract the ZIP, then open fanout-kit-v2 in a terminal. npm ci installs the locked dependencies; tests and parsing then run offline. The kit was checked with Node.js 24.15.0. Strings in fixtures.mjs are original teaching data, not newly retained OpenAI responses.

Continue with interpret a published OpenAI observation.

Run after extraction
npm ci --ignore-scripts
npm test
npm run validate

Three strings do not mean three actions

The synthetic example exposes example topic and example cost in one action, then example import in another. The parser returns three strings and two search actions. A flat query list helps selection; actions also preserves the grouping needed for a later source review.

The fictional example.com/guide source stays with the first action. That action contains two queries, so the parser assigns it to neither individual query. An answer annotation enters runSources with run scope. Even a single-string action does not prove every source exclusively answers that string; the teaching example conservatively keeps action scope.

Run the short example inside the kit folder, or save it there as your own .mjs file. Its result follows the teaching parser's contract, not the website's JSON export. Use an explicit adapter if your consumer expects another contract, retaining the original evidence boundaries.

Continue with audit source scope.

Parse a synthetic response offline
import { parseOpenAiResponse } from "./parsers.mjs";
import { fixtures } from "./fixtures.mjs";
const result = parseOpenAiResponse(fixtures.openai);
console.log(result.queries); // three exposed strings
console.log(result.searchActionCount); // 2
console.log(result.actions[0].sourceScope); // search_action

Partial output, normalization and version boundaries

An incomplete response with visible strings becomes partial. Without strings, its count remains unknown. A completed response with valid output but no search strings has zero exposed strings. Missing status stays unknown; an invalid container throws INVALID_RESPONSE. Different failure classes remain distinguishable.

The teaching parser preserves Unicode, case, whitespace, duplicates and occurrence order. The current website wrapper instead normalizes to NFC, trims, deduplicates and caps the visible list at eight strings. It also counts web_search_call objects and uses some fallback metadata. The README documents these deliberate differences; do not copy the example as an unchecked production replacement.

Continue with run the parser checks.

The tests check the contract reviewed on 10 October 2026. They establish code behavior for the included cases, not exhaustive coverage of future provider responses. Add a test when a field or action changes. Passing parser tests proves neither human search volume nor a stable AI citation.

Sources used

These sources support the functions and limits described here. They do not prove claims beyond that scope.

  1. OpenAI Responses: web-search action fields

    Supports exposed action query fields, distinct search/open/find action types and URL annotations. The documentation does not provide private consumer traces or guarantee every run exposes strings.

    Open source
  2. Original runnable offline parser and edge-case test kit

    Original educational parser code and 27 offline checks. Synthetic response fixtures are not provider output; exact strings, status states, source scope and retention exclusions are tested. No paid calls or new actual grounding data. The teaching helper explicitly differs from the live normalized wrapper.

    Open source
  3. Current website export contracts and reference validation

    Draft 2020-12 reference for the current native/modelled full runs, query selections and local comparisons. Schema checked against actual service/export functions with synthetic provider stubs and semantic negative tests. No root schemaVersion is invented for full runs. Legacy planner and handoff formats remain separate.

    Open source