Ask ChatGPT
GET /chatgpt — bearer auth, JSON responses, billed per successful request.
Ask ChatGPT
Sends a prompt to ChatGPT through a browser automation and returns the response as structured JSON with citations preserved. The crawler opens chatgpt.com, types the prompt character by character, waits for the streamed answer, and converts it into typed nodes—paragraphs, headings, lists, tables, product lists.
When to use it. Use this when you need ChatGPT's output with inline citations intact, or when you want the answer shaped by a specific geographic origin without managing proxies or browser infrastructure yourself. For simple text extraction from static pages, /crawl is cheaper and faster.
Notes
- Flat 30 credits.
premium,country, andcityaffect routing and access but never change the price, unlike on/crawl. - Prompts are typed slowly. The 1000-character limit exists because each character is typed individually; a long prompt consumes significant time before ChatGPT begins responding.
- Collect 202s via `/crawl/{job}`. Slow prompts return 202; poll the crawl collection endpoint. The answer nests under
data.conversation, not top-levelconversation.
| Parameter | In | Type | Description |
|---|---|---|---|
| prompt * | query | string | The question, up to 1000 characters. The limit is not arbitrary. The prompt is typed one character at a time, so a thousand characters is already half a minute of typing before ChatGPT starts to think -- against a crawler that waits about two and a half minutes for the whole job. |
| premium | query | string | Ask through the premium proxy pool rather than the standard one. **On by default**, because the standard pool is the one ChatGPT turns away; send `false` to use the standard pool. Free either way, unlike on `/crawl` -- the price is flat. Sent as text in a query string, so the spellings a person would reach for all work: `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off`, in any case. Anything that is not a yes or a no is refused rather than quietly read as `false`. |
| country | query | string | The country to appear to be asking from, as a two-letter ISO 3166-1 alpha-2 code. Free, and it changes what ChatGPT answers as much as it changes anything -- a question about prices asked from Germany is not the same question. Required to use `city`. |
| city | query | string | The city inside that country, as the pool spells it. **Requires `country`.** Free here, where on `/crawl` it doubles the price. Letters, digits, hyphens and underscores only; a multi-word city is written `new_york`. |
| key | query | string | The API key, as an alternative to the `Authorization` header. Ignored when a header is present. A key in a url is copied into access logs, proxy logs and `Referer` headers, which is a fair trade for a machine-to-machine endpoint and a bad one for anything else. |
curl -X GET "https://app.irmu.com/api/chatgpt?prompt=&premium=&country=&city=&key=" \
-H "Authorization: Bearer $IRMU_API_KEY"{
"prompt": "elon musk",
"conversation": [
{
"role": "user",
"message": "elon musk"
},
{
"role": "assistant",
"response": [
{
"type": "paragraph",
"text": "Elon Musk is a businessman known for Tesla and SpaceX.",
"sources": [
{
"attribution": "Reuters",
"url": "https://example.com/article"
}
]
},
{
"type": "heading",
"level": 2,
"text": "Companies"
},
{
"type": "bullet_list",
"items": [
{
"text": "Tesla"
},
{
"text": "SpaceX"
}
]
}
]
}
],
"credits_charged": 30,
"credits_remaining": 970,
"job_id": "0198a9b6-1f4c-7c3e-9a2b-5d8e6f0a1b23_0198a9b6-2a71-7f0d-8c44-9e1b3c5d7f02",
"status": "done",
"position": null,
"error": null
}Guides using this endpoint
- How to Give Claude, ChatGPT and Cursor Live Web Access with an MCP Server
- Build Your Own AI Overview Tracker: Monitor Google AI Overviews by Keyword (2026)
- ChatGPT Brand Monitoring: Track What AI Tells Your Customers (2026)
const res = await fetch("https://app.irmu.com/api/chatgpt", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.IRMU_API_KEY}`,
"Content-Type": "application/json",
}
});
const data = await res.json();import os, requests
res = requests.get(
"https://app.irmu.com/api/chatgpt",
headers={"Authorization": f"Bearer {os.environ['IRMU_API_KEY']}"}
)
print(res.json())| Status | Meaning |
|---|---|
| 200 | ChatGPT answered. `conversation` holds the exchange: your prompt, then the answer as a list of nodes. |
| 202 | Paid for and still going. A long prompt can outlast the crawler's patience for waiting, though not its patience for working. Collect it from `/crawl/{job}` -- the same endpoint a slow crawl is collected from, and free in the same way. One difference worth knowing: that endpoint answers the crawl envelope, so the answer arrives under `data.conversation` rather than lifted into `conversation` the way it is here. With `debuga=1`, a prompt that is still running also carries `debug`: the url, a viewport screenshot and the page source as they stood when the crawler stopped waiting, so a slow prompt shows the chat as it was rather than nothing at all. Null once it finishes -- the tab is gone by then. It costs nothing. |
| 401 | No key, an unknown key, or a caller that is not an organization. |
| 402 | Not enough credits, or the daily limit is reached. Nothing is charged and no attempt is recorded. |
| 422 | A malformed request -- no prompt, a prompt over the limit, a city with no country, or a flag that is not a yes or a no. |
| 500 | Nothing came back. Either the crawl failed outright, or ChatGPT did not answer within its timeout -- which reads as an empty `conversation` and an `error` saying so. **The credits are refunded either way**, so `credits_charged` is `0`. The attempt is still recorded against `chatgpt.com`, so a customer can see that we tried. |
Start building with Irmu today
200 free credits every month, no card required. Every API, every integration, one key.