Ask Gemini
curl --request GET \
--url https://scrapebadger.com/v1/gemini/ask \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <x-api-key>' \
--data '
{
"image_base64": "<string>"
}
'import requests
url = "https://scrapebadger.com/v1/gemini/ask"
payload = { "image_base64": "<string>" }
headers = {
"X-API-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.get(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'X-API-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({image_base64: '<string>'})
};
fetch('https://scrapebadger.com/v1/gemini/ask', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://scrapebadger.com/v1/gemini/ask",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_POSTFIELDS => json_encode([
'image_base64' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://scrapebadger.com/v1/gemini/ask"
payload := strings.NewReader("{\n \"image_base64\": \"<string>\"\n}")
req, _ := http.NewRequest("GET", url, payload)
req.Header.Add("X-API-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://scrapebadger.com/v1/gemini/ask")
.header("X-API-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"image_base64\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://scrapebadger.com/v1/gemini/ask")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"image_base64\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"prompt": "<string>",
"answer": "<string>",
"answer_markdown": {},
"citations": [
{
"url": {},
"title": {},
"snippet": {},
"domain": {},
"attribution": {},
"start_index": {},
"end_index": {},
"matched_text": {}
}
],
"search_results": [
{
"url": {},
"title": {},
"snippet": {},
"domain": {},
"attribution": {},
"cited": true
}
],
"images": [
{
"url": "<string>",
"title": {}
}
],
"source_domains": [
"<string>"
],
"web_search_triggered": true,
"truncated": true,
"model": {},
"conversation_id": {},
"message_id": {},
"country": "<string>",
"answer_length": 123,
"citation_count": 123,
"latency_ms": 123,
"created_utc": {},
"created_at": {}
}Ask
Ask Gemini
Send a prompt to the real gemini.google.com and get the answer as structured JSON, with citations anchored to character offsets in the answer text.
GET
/
v1
/
gemini
/
ask
Ask Gemini
curl --request GET \
--url https://scrapebadger.com/v1/gemini/ask \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <x-api-key>' \
--data '
{
"image_base64": "<string>"
}
'import requests
url = "https://scrapebadger.com/v1/gemini/ask"
payload = { "image_base64": "<string>" }
headers = {
"X-API-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.get(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'X-API-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({image_base64: '<string>'})
};
fetch('https://scrapebadger.com/v1/gemini/ask', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://scrapebadger.com/v1/gemini/ask",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_POSTFIELDS => json_encode([
'image_base64' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://scrapebadger.com/v1/gemini/ask"
payload := strings.NewReader("{\n \"image_base64\": \"<string>\"\n}")
req, _ := http.NewRequest("GET", url, payload)
req.Header.Add("X-API-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://scrapebadger.com/v1/gemini/ask")
.header("X-API-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"image_base64\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://scrapebadger.com/v1/gemini/ask")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"image_base64\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"prompt": "<string>",
"answer": "<string>",
"answer_markdown": {},
"citations": [
{
"url": {},
"title": {},
"snippet": {},
"domain": {},
"attribution": {},
"start_index": {},
"end_index": {},
"matched_text": {}
}
],
"search_results": [
{
"url": {},
"title": {},
"snippet": {},
"domain": {},
"attribution": {},
"cited": true
}
],
"images": [
{
"url": "<string>",
"title": {}
}
],
"source_domains": [
"<string>"
],
"web_search_triggered": true,
"truncated": true,
"model": {},
"conversation_id": {},
"message_id": {},
"country": "<string>",
"answer_length": 123,
"citation_count": 123,
"latency_ms": 123,
"created_utc": {},
"created_at": {}
}Ask the real
gemini.google.com a question anonymously and get the answer
back as JSON — plus every web source Gemini retrieved, which of those it cited,
and exactly which span of the answer each citation supports.
Accepts GET (query params) or POST (JSON body) with identical fields.
Credits: 20
This is a live answer, not a cache — with web search the call can take tens
of seconds. Set your client timeout to at least 60 s.
Authorization
string
required
Your ScrapeBadger API key.
Query Parameters
string
required
The question to ask. Maximum 4,096 characters. Each request is standalone
— there is no conversation memory, so include all the context you need here.
string
default:"US"
ISO-3166 alpha-2 egress country, e.g.
US, GB, DE. Changes the localised
results Gemini retrieves.string
default:"auto"
Whether Gemini should ground the answer with a web search. One of:
auto— let Gemini decide (default).force— instruct it to search the web.off— answer from the model’s own knowledge only.
web_search_triggered in the response for what actually happened.string
deprecated
Not supported — returns
422. Signed-out Gemini refuses image questions,
so this fails immediately and is never billed. Use
ChatGPT /ask for image input.string
deprecated
Not supported — returns
422. Same as image_url above.Anonymous gemini.google.com neither reads nor GENERATES images — its
logged-out page gates both behind a login — so no request to this endpoint can
answer about a picture or return one it drew.
images in the response is what
the answer displayed.Response
string
Echo of the prompt you sent.
string
The answer as plain text. Citation offsets index into this string.
string | null
The answer with its original Markdown formatting, when available.
Citation[]
The sources Gemini actually referenced in the answer.
Show Citation
Show Citation
string | null
Source URL.
string | null
Page title.
string | null
Snippet Gemini retrieved from the page.
string | null
Hostname, e.g.
techcrunch.com.string | null
Publisher/attribution label as shown by Gemini.
integer | null
Character offset in
answer where the supported span begins.integer | null
Character offset in
answer where the supported span ends.string | null
The substring of
answer this source supports.SearchResult[]
The full set Gemini retrieved — including results it looked at but did
not cite. Empty when
web_search_triggered is false.MediaItem[]
string[]
Distinct hostnames across the cited sources — a quick view of who Gemini trusted.
boolean
Whether Gemini actually grounded this answer with a web search.
boolean
true when the render budget expired while Gemini was still writing, so answer is the partial text produced so far.string | null
Which model answered — a Gemini Flash-Lite build. Reported, not requestable.
string | null
Identifier of the one-shot exchange. Not a handle you can continue from.
string | null
Identifier of the answer message.
string
Echo of the egress country used.
integer
Length of
answer in characters.integer
Number of entries in
citations.integer
End-to-end time to produce the answer, in milliseconds.
number | null
Answer creation time as a Unix timestamp.
string | null
Answer creation time as an ISO-8601 UTC string.
Example
curl "https://scrapebadger.com/v1/gemini/ask?prompt=Which%20companies%20lead%20the%20web%20scraping%20API%20market%3F&country=US&web_search=force" \
-H "X-API-Key: YOUR_API_KEY" \
--max-time 60
const res = await fetch("https://scrapebadger.com/v1/gemini/ask", {
method: "POST",
headers: {
"X-API-Key": process.env.SCRAPEBADGER_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: "Which companies lead the web scraping API market?",
country: "US",
web_search: "force",
}),
signal: AbortSignal.timeout(60_000),
});
const data = await res.json();
for (const c of data.citations) {
console.log(`${c.domain} → "${c.matched_text}"`);
}
import requests
res = requests.post(
"https://scrapebadger.com/v1/gemini/ask",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"prompt": "Which companies lead the web scraping API market?",
"country": "US",
"web_search": "force",
},
timeout=60,
)
data = res.json()
for c in data["citations"]:
print(c["domain"], "→", data["answer"][c["start_index"]:c["end_index"]])
Response
{
"prompt": "Which companies lead the web scraping API market?",
"answer": "The web scraping API market in 2026 is led by a handful of infrastructure providers. Bright Data remains the largest by revenue, with a proxy network spanning residential and mobile exits. Oxylabs and Zyte compete directly on enterprise contracts, while newer entrants such as ScrapeBadger and ScrapingBee focus on per-endpoint APIs with predictable credit pricing.",
"answer_markdown": "The web scraping API market in 2026 is led by a handful of infrastructure providers. **Bright Data** remains the largest by revenue, with a proxy network spanning residential and mobile exits. **Oxylabs** and **Zyte** compete directly on enterprise contracts, while newer entrants such as **ScrapeBadger** and **ScrapingBee** focus on per-endpoint APIs with predictable credit pricing.",
"citations": [
{
"url": "https://research.example.com/web-scraping-market-2026",
"title": "Web Scraping Market Report 2026",
"snippet": "Bright Data continues to hold the largest share of the commercial web data market...",
"domain": "research.example.com",
"attribution": "Example Research",
"start_index": 103,
"end_index": 213,
"matched_text": "Bright Data remains the largest by revenue, with a proxy network spanning residential and mobile exits."
},
{
"url": "https://news.example.org/scraping-api-pricing-shakeup",
"title": "The scraping API pricing shakeup",
"snippet": "Credit-based per-endpoint pricing has become the default for newer vendors...",
"domain": "news.example.org",
"attribution": "Example News",
"start_index": 214,
"end_index": 366,
"matched_text": "Oxylabs and Zyte compete directly on enterprise contracts, while newer entrants such as ScrapeBadger and ScrapingBee focus on per-endpoint APIs with predictable credit pricing."
}
],
"search_results": [
{
"url": "https://research.example.com/web-scraping-market-2026",
"title": "Web Scraping Market Report 2026",
"snippet": "Bright Data continues to hold the largest share of the commercial web data market...",
"domain": "research.example.com",
"attribution": "Example Research",
"cited": true
},
{
"url": "https://news.example.org/scraping-api-pricing-shakeup",
"title": "The scraping API pricing shakeup",
"snippet": "Credit-based per-endpoint pricing has become the default for newer vendors...",
"domain": "news.example.org",
"attribution": "Example News",
"cited": true
},
{
"url": "https://forum.example.net/thread/best-scraping-api",
"title": "Best scraping API in 2026? — discussion",
"snippet": "Long thread comparing per-request costs across eight vendors...",
"domain": "forum.example.net",
"attribution": null,
"cited": false
}
],
"source_domains": ["research.example.com", "news.example.org"],
"web_search_triggered": true,
"truncated": false,
"model": "gemini-flash-lite",
"conversation_id": "6a1f2c9e-3d54-4b17-9f0a-2c7de51b8a44",
"message_id": "b03d7f18-5c2a-49e6-8f31-77d1c0a9e512",
"country": "US",
"answer_length": 366,
"citation_count": 2,
"latency_ms": 24817,
"created_utc": 1754323200.0,
"created_at": "2026-08-04T16:00:00Z"
}
search_results is the full retrieved set; citations is the subset that made
it into the answer. When web_search_triggered is false, both are empty and
Gemini answered from its own knowledge — that is a valid response, not an
error.Asking about an image
Gemini cannot answer about an image, and this endpoint no longer tries.Passing
image_url or image_base64 returns 422 with
"code": "image_not_supported". Nothing is billed and no browser is spent.The upload itself works — the picture reaches Google and the prompt reaches
the conversation — but signed-out sessions get PERMISSION_DENIED back from
Gemini’s own answer-generation call, so no answer is ever produced. The same
request without a picture answers normally in a few seconds. This is a Google
restriction on anonymous sessions, not a limit we impose, and there is no
request shape that works around it.Use ChatGPT /ask instead — it
takes image_url or image_base64 and answers about the picture.Returns 422
curl -X POST "https://scrapebadger.com/v1/gemini/ask" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "What is in this photo?", "image_url": "https://example.com/a.jpg"}'
# {"detail":{"code":"image_not_supported",
# "message":"Gemini refuses image questions for signed-out sessions
# (PERMISSION_DENIED on its own generate RPC).
# Use /v1/chatgpt/ask for image input."}}
Gemini is non-deterministic. The same prompt can return different wording and
different sources on each call. For tracking, sample on a schedule and
aggregate.

