Docs menu
- Docs
- Start
- Troubleshooting
Troubleshooting
Find what you see in the list below. Each entry says why it happens and what to change. An error is never charged. Every answer carries X-Request-Id: quote it if you write to support. The full list of codes is in Error codes.
Print the status, our headers and the body of any call with -sS -D -:
curl -sS -D - -o page.out "https://get.megalania.io/v1?url=https://docs.megalania.io/start/quickstart" \ -H "Authorization: Bearer $MEG_API_KEY"
The key
401 bad_token
The message says which of five it is:
-
“No API key was sent”: no
Authorizationheader reached us. -
“The Authorization header has no Bearer”: write
Authorization: Bearer <key>, not just the key. -
“The key was sent in an X-Api-Key header”: we read only
Authorization. -
“A key in the URL is refused”: remove
api_keyfrom the URL. -
“The API key is wrong, expired or deleted”: the header is right, the key is not.
-
Run
echo ${MEG_API_KEY:0:7}. It must printmeg_sk_. Empty means the shell that runs the call has no key:exportit in that shell. -
Send
Authorization: Bearer $MEG_API_KEY. A key in the URL (?api_key=) is refused, even next to the header. -
Copy-paste can add a space or a line break. Paste the key between single quotes, as in the quickstart.
-
Still 401? Make a new key on the API keys page. We store only a hash, so a lost key cannot be shown again.
403 wrong_scope
The key has the wrong scope. A key that starts with meg_ak_ is an account
key: it manages the account and cannot scrape. Use a scrape key, meg_sk_.
The other way round, a scrape key cannot manage the account; only
GET /v1/account takes both.
403 notice_required
You have not accepted the current beta notice. Sign in to the dashboard, read the notice and press I agree. Then make the key, or connect the agent, again.
The address
404 with an empty body on /v1/batches
Batches live on the API host, https://api.megalania.io. The scrape host,
https://get.megalania.io, serves only /v1, /v1/map, /v1/tier,
/v1/stats/domain and /v1/geos. Change the host, keep the path.
400 bad_parameter
Read error.field: that parameter is missing, misspelled, or has a value we
do not accept. The message lists the values that work. The four we see most:
- An unknown parameter. We never ignore one.
render=truefrom an old script is a 400 namingrender. Sendengine=browser. - A number with a fraction or a sign.
timeout,max_creditsandmax_agetake a whole JSON number or a string:"timeout": 30and"timeout": "30"both work;30.5or-1is a 400 naming the key. - A query string we cannot read. On
GET /v1, puturllast and paste it as it is, or percent-encode it. Idempotency-Keytoo long or not ASCII. Send 1 to 128 printable ASCII characters. A UUID works.
415 unsupported_media_type
Every POST takes JSON. Add -H "Content-Type: application/json", even
with an empty {} body.
The page
200, but the page is empty or is only a script shell
Look at X-Hint. needs_js means the page builds its content with
JavaScript. Two fixes, cheapest first:
- Ask for
"response_types": "page_data". Many pages carry their data as JSON in the HTML, at the HTTP price. - Send
"engine": "browser". We render the page in Chrome. It costs more: see Credits and pricing.
No X-Hint and still too little text? A short answer can still be a shell.
Try the same two steps.
422 blocked
The site blocked every route we tried, and there is nothing to show. It is
free: X-Billing: blocked says so. A block is always this 422, never a
200. Read the headers:
-
X-Hopslists each try, likeh:dc:chrome=3826,h:res:chrome=4989. -
X-Untriednames the routes we did not try, such asc:res. The climb stops early when the next step costs more than it is likely to win. To try one yourself, ask for it by name:route send h:res"engine": "http", "proxy_tier": "residential"c:dc"engine": "browser"c:res"engine": "browser", "proxy_tier": "residential"A residential or browser page costs more: see Credits and pricing.
-
X-Untried-Reason: budgetmeans residential routes are unavailable right now, so the climb skipped every residential route and tried the next open one. A skipped route is never charged. -
No
X-Untriedmeans every route was tried. Retrying will not help today. -
X-Target-Statusis what the site answered, often403.
X-Target-Status: 404 (or any status under 500)
The site itself answered with that status, and that is the result: you pay for it like any page. Check the URL in a browser.
422 convert_cap or 422 upstream_cap
The page is too large to convert, or pulled more data than one request may
use. It is refunded. Ask for html instead of markdown, or fewer
response_types, or fetch a smaller page.
422 document_unreadable
The url answered with a PDF, Word, PowerPoint or Excel file we cannot read.
It holds only scanned images, it needs a password, it is damaged, or reading
it ran past our memory or time limits. It is free. We do not run OCR yet, so
a scanned PDF stays unreadable. A file over 64 MiB unpacked, or over 500
slides, is a 422 convert_cap instead.
A host name that does not exist
Today you get 503 fetch_error, free, after we tried the other routes.
The 422 unknown_host code is in the error list, but the DNS check behind it
is switched off, so it is not sent yet. See errors.
- Check the spelling of the host, and whether you left out a
www.. - A new domain can take a few minutes to appear in DNS. Retry later.
X-Truncated on a 200
The page reached the most bytes this request may pull, and we kept the part
that fit. max_credits: raise it, or remove it, for the whole page.
byte_cap: the route’s or your plan’s byte cap, or your balance, stopped it.
Money and limits
402 insufficient_credits
Your balance is lower than the cheapest route for this page. In the beta,
write to [email protected] and we add credits.
proxy_tier=datacenter makes a request cheaper.
400 max_credits_too_low
Every route for this page costs more than your max_credits. The message
names the lowest price on that site. Raise max_credits to at least that.
Run check a site first before a big run:
it is free.
429 codes
| code | what to do |
|---|---|
over_concurrency |
Too many requests at once. Wait the seconds in Retry-After. |
rate_limited |
Batches, monitors and the account API take 2 calls a second. Wait the seconds in Retry-After. |
target_rate_limited |
The site is rate limiting. We hold your requests to it until Retry-After ends, so you do not pay for more 429s. |
daily_cost_cap |
Today’s usage limit is used up. It resets at 00:00 UTC. |
period_cost_cap |
Your grant’s usage limit is used up. In the beta, write to [email protected]. |
409 replayed
You already used this Idempotency-Key in the last 24 hours, and the first
call went through. Do not retry. Use a new key for a new request.
503 llm_unavailable with schema
Schema extraction could not run: it is not set up right now, or the model did not answer in time. The extraction is always free. What about the page:
- The body carries
markdown. We fetched the page, and you paid for the page only:X-Credits-Chargedandcreditsin the body say how much, andllm_creditsis 0. The page is there, so you can read it yourself. - No
markdownin the body. We stopped before the fetch. Nothing was charged.
Retry later. extract with CSS rules needs no model and works now:
Fetch, extract and lists shows how.
503 busy, timeout or fetch_error
These are refunded. Wait the seconds in Retry-After if there is one, and
send the same request with the same Idempotency-Key. You are charged once.
timeout: raise timeout, up to "90".
MCP
The client shows no tools, or every call is 401
- Claude Code: type
/mcp, pickmegalaniaand finish the sign-in in the browser. Press Approve on the Megalania page. - Cursor and VS Code: the key goes in
headers, as"Authorization": "Bearer meg_sk_...". Restart the client after you editmcp.json. - The server address is
https://mcp.megalania.iowith nothing after it. A?in the address is a 400.
Check the server from your shell. A 200 with the tools in result.tools
means your key and the server are fine, and the problem is the client’s
config:
curl -sS -X POST https://mcp.megalania.io/ \
-H "Authorization: Bearer $MEG_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2026-07-28" \
-H "Mcp-Method: tools/list" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"curl","version":"8"},"io.modelcontextprotocol/clientCapabilities":{}}}}'A tool result says ok: false
Do what next_step says. It names the argument to change, or tells the
agent to call again later. Blocked pages and errors are free.
Still stuck
Report it at https://app.megalania.io/report, or write to
[email protected]. Send the
X-Request-Id, what you sent (without the key) and what you expected. We
never need your key.