ChatGPT vs Gemini vs Perplexity: Response Structure Compared
Lead Scraping Automation Engineer
TL;DR:
- Three actors, one transport, three answer shapes.
scraper.chatgpt,scraper.gemini, andscraper.perplexityall POST to the same endpoint and return the same{ status, task_id, task_result }envelope β but the fields insidetask_resultdiffer by actor. - The "sources" field has a different name on each. ChatGPT returns
content_referencesandsearch_result; Gemini returnscitations; Perplexity returnsweb_resultsβ the same idea, three keys, three per-item shapes. The field you read to get the sources is not portable across the three. - Only ChatGPT returns products. With
shoppingenabled,scraper.chatgptadds aproductsarray with per-merchantoffers; Gemini and Perplexity return no shopping surface. - Perplexity carries the richest envelope. On top of the answer and
web_results, it returns amedia_itemsarray and arelated_promptlist; Gemini is the leanest β answer text plus acitationsarray and nothing else. - Input flags differ by actor. All take
promptandcountryinsideinput; ChatGPT adds an optionalshoppingflag, Perplexity addsweb_search. Parameters always go insideinput, never at the top level. - Every field is nullable and per-session. An array can come back empty on a given run, so the actor you pick decides which fields you can rely on β store
task_idand a capture timestamp and read the series, not one call. - Free to start. New Scrapeless accounts include free trial credits β sign up at app.scrapeless.com.
Introduction: one prompt, three response shapes
Send the same question to ChatGPT, Gemini, and Perplexity through Scrapeless and three answers come back β in three different JSON shapes. The transport is identical: one POST, one x-api-token header, one { status, task_id, task_result } envelope. What changes is the inside of task_result β the key that holds the answer's sources, whether products come back, whether media and follow-up prompts are included. A client that reads one of these actors does not automatically read the other two.
This is a developer comparison of the returned schemas, not a verdict on which model answers better. It maps, field by field, what scraper.chatgpt, scraper.gemini, and scraper.perplexity actually return for the same prompt, where the schemas diverge, and which actor to capture for which job. For the best LLM scrapers view of the tool category itself, that guide ranks the surfaces; this one lays their response shapes side by side.
What each actor captures
All three are Universal Scraping API LLM actors, captured the same way:
scraper.chatgptβ ChatGPT's synthesized answer, the sources it cited, and (withshoppingon) a product carousel with per-merchant offers.scraper.geminiβ Gemini's answer plus a citations array. The leanest of the three.scraper.perplexityβ Perplexity's answer, its web-result sources, inline media, and the follow-up prompts it suggests.
The shared contract: same endpoint, same envelope, same auth
All three actors POST to https://api.scrapeless.com/api/v2/scraper/execute with an x-api-token header and a body of { actor, input: { prompt, country, β¦ } }, and all three return { status, task_id, task_result }. Swapping actors is a one-line change.
bash
curl -sS -X POST https://api.scrapeless.com/api/v2/scraper/execute \
-H "Content-Type: application/json" \
-H "x-api-token: ${SCRAPELESS_API_KEY}" \
-d '{ "actor": "scraper.gemini", "input": { "prompt": "best running shoes 2026", "country": "US" } }'
# actor: scraper.chatgpt | scraper.gemini | scraper.perplexity
The transport is portable; the parsing is per-actor β task_result is where they diverge.
The answer body, compared
Every actor returns the synthesized answer as result_text (markdown-flavored prose). That field name is the one thing the answer body shares across all three. None of the three returns separate markdown and HTML variants of the answer β result_text is the single answer format here. (The scraper.aimode actor, a different surface, is the one that splits the answer into text/markdown/HTML; these three do not.)
Where the schemas diverge: citations and sources
"What did the model cite" is the same question for all three actors and a different field on each:
- ChatGPT splits it in two:
content_references[](the cited sources, each withtitle,url,attribution) andsearch_result[](the web results it consulted, withtitle,url,snippet,attribution), gated by aweb_searchboolean. - Gemini returns a single
citations[]array, and it is the most detailed per item:title,url,website_name,snippet,favicon, andhighlights. - Perplexity returns
web_results[], the leanest source item:name,url,snippet.
Same concept, three keys, three shapes. A share-of-citation parser written against Gemini's citations[].website_name does not run against Perplexity's web_results[].name without remapping.
Platform-unique fields
Each actor returns something the other two do not:
- ChatGPT β products. Set
input.shopping: trueandscraper.chatgptadds aproducts[]array, each product carrying a price, rating, review count, and anoffers[]list with one entry per merchant. It also returns amodelid and alinks[]array. Gemini and Perplexity have no shopping surface. - Perplexity β media and follow-ups.
scraper.perplexityreturns amedia_items[]array (image,thumbnail,url,source,medium) and arelated_prompt[]list of suggested follow-up questions β neither of which the other two return. - Gemini β nothing extra. Gemini's value is the opposite: a clean two-field answer (
result_text+citations[]) with no platform-specific surface to handle.
The field matrix: all three side by side
| Conceptual field | scraper.chatgpt |
scraper.gemini |
scraper.perplexity |
|---|---|---|---|
| Answer text | result_text |
result_text |
result_text |
| Cited sources | content_references[] (title, url, attribution) |
citations[] (title, url, website_name, snippet, favicon, highlights) |
web_results[] (name, url, snippet) |
| Web-search results | search_result[] + web_search flag |
β | web_results[] |
| Products / offers | products[] + offers[] (with shopping: true) |
β | β |
| Media | β | β | media_items[] |
| Related prompts | β | β | related_prompt[] |
| Model id | model |
β | β |
| Links | links[] |
β | β |
| Echoed prompt | prompt |
prompt |
prompt |
| Optional input flag | shopping |
β | web_search |
Read down a column to know which fields an actor gives you; read across a row to see why one parser cannot serve all three.
Get your API key on the free plan: app.scrapeless.com
Input parameters, compared
The input object is where the request-side asymmetry lives. All three require prompt and country; the optional flags differ.
input field |
scraper.chatgpt |
scraper.gemini |
scraper.perplexity |
|---|---|---|---|
prompt |
required | required | required |
country |
required | required | required |
shopping |
optional (β products[]) |
β | β |
web_search |
optional | β | optional |
Every field sits inside input; sending prompt or country at the top level of the body is rejected.
Volatility and nullability across the three
The answer is generated per session, so the same prompt returns different text and different array lengths from one run to the next, on every actor. Treat each field as nullable: products[] can be empty even with shopping on, citations[] and web_results[] vary in count, and a persistently empty array means there was no answer for that query β not something to send again. Store task_id and a capture timestamp on every call so the time series is the signal, not a single response.
Decision guide: which response shape to capture for which job
| If the job is⦠| Capture | Read |
|---|---|---|
| Cross-merchant price / product monitoring | scraper.chatgpt with shopping: true |
products[] β offers[] |
| Share-of-citation with rich source metadata | scraper.gemini |
citations[] (website_name, highlights) |
| Source tracking plus media and follow-up intent | scraper.perplexity |
web_results[], media_items[], related_prompt[] |
| Leanest answer-only capture | scraper.gemini |
result_text |
Pin the actor to the question. Because the transport is shared, running two or three of them on the same prompt and country is the same client with a different actor string β and gives you the answer from each platform's surface in one pass.
Conclusion: three shapes, one client
The transport is shared and the parsing is not: scraper.chatgpt, scraper.gemini, and scraper.perplexity answer to the same endpoint and envelope, but task_result diverges β different source keys, ChatGPT-only products, Perplexity-only media and follow-ups, Gemini's lean two-field shape. Pick the actor by the field you need, map task_result per actor, and treat every field as nullable. Run a fixed prompt set on a schedule with Universal Scraping API credits, and one client captures all three platforms' answers. The field names here are confirmed against live runs of each actor in the LLM Chat Scraper reference.
Ready to Build Your AI-Answer Data Pipeline?
Join our community to claim a free plan and connect with developers building AI-answer data pipelines: Discord Β· Telegram.
Sign up at app.scrapeless.com for free trial credits and point one client at ChatGPT, Gemini, and Perplexity to capture all three answer shapes on the queries your program tracks.
FAQ
Q: Do all three actors take the same input?
All three take prompt and country inside the input object. scraper.chatgpt adds an optional shopping flag and scraper.perplexity adds web_search; parameters always go inside input, never at the top level.
Q: Why are the citation fields named differently across the three?
Each actor parses its own platform's rendered answer, so the source data is shaped per platform β ChatGPT's content_references, Gemini's citations, and Perplexity's web_results carry different keys and different per-item fields. Read the field that actor returns rather than assuming a shared key.
Q: Can one client read all three without a rewrite?
For transport, yes β the same endpoint, x-api-token header, and { status, task_id, task_result } envelope. You swap the actor name and map the task_result keys per actor, because the inner field set differs.
Q: Which actor returns shopping or product data?
scraper.chatgpt with input.shopping: true populates a products[] array with per-merchant offers[]. Gemini and Perplexity do not return a shopping surface.
Q: Why does the same prompt return different fields on different runs?
Answers are generated per session and vary run to run; every field is nullable and an array can come back empty. Treat a persistently empty result as no answer for that query, and store task_id plus a capture timestamp so the series is the signal.
At Scrapeless, we only access publicly available data while strictly complying with applicable laws, regulations, and website privacy policies. The content in this blog is for demonstration purposes only and does not involve any illegal or infringing activities. We make no guarantees and disclaim all liability for the use of information from this blog or third-party links. Before engaging in any scraping activities, consult your legal advisor and review the target website's terms of service or obtain the necessary permissions.



