Docs menu
- Docs
- Start
- Quickstart
Quickstart
Four steps, about ten minutes. Make a key, fetch one page, connect your AI agent over MCP, and run one batch. Every block below runs as pasted once MEG_API_KEY is set. Each step works on its own, so stop where you have what you need.
-
Get a key (2 minutes)
Open
https://app.megalania.io/loginand sign in with Google or GitHub. There is no password. In the beta, only invited emails can sign in. Your beta account starts with 76,000 credits for 30 days.Open API keys and press Create key. A scrape key starts with
meg_sk_. We show it once, so copy it now. Then put it in your shell:Shellexport MEG_API_KEY='meg_sk_your_key_here'
Send the key in the
Authorizationheader only. A key in a URL is refused with401 bad_token. A new key works within a second, at most a minute. Get a key has the details. -
Fetch one page (2 minutes)
This asks for this page, from our own docs, as Markdown. Pick your language:
: "${MEG_API_KEY:?Set MEG_API_KEY first}" # export MEG_API_KEY=YOUR_KEY curl -X POST https://get.megalania.io/v1 \ -H "Authorization: Bearer $MEG_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid)" \ -d '{"url":"https://docs.megalania.io/start/quickstart","response_types":"markdown"}' \ --fail-with-body -D - -o page.md# export MEG_API_KEY=YOUR_KEY import os import uuid import requests resp = requests.post( "https://get.megalania.io/v1", headers={"Authorization": f"Bearer {os.environ['MEG_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())}, json={ "url": "https://docs.megalania.io/start/quickstart", "response_types": "markdown", }, timeout=90, ) print(resp.status_code, resp.headers.get("X-Credits-Charged"), resp.headers.get("X-Route")) print(resp.text[:500])// export MEG_API_KEY=YOUR_KEY const res = await fetch("https://get.megalania.io/v1", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEG_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ "url": "https://docs.megalania.io/start/quickstart", "response_types": "markdown" }), }); console.log(res.status, res.headers.get("x-credits-charged"), res.headers.get("x-route")); console.log((await res.text()).slice(0, 500));// export MEG_API_KEY=YOUR_KEY package main import ( "crypto/rand" "fmt" "io" "log" "net/http" "os" "strings" ) func main() { body := strings.NewReader(`{"url":"https://docs.megalania.io/start/quickstart","response_types":"markdown"}`) req, err := http.NewRequest("POST", "https://get.megalania.io/v1", body) if err != nil { log.Fatal(err) } req.Header.Set("Authorization", "Bearer "+os.Getenv("MEG_API_KEY")) req.Header.Set("Content-Type", "application/json") req.Header.Set("Idempotency-Key", rand.Text()) resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() page, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, resp.Header.Get("X-Credits-Charged"), len(page)) }The cURL example prints our headers and saves the page in
page.md:Response headersHTTP/2 200 content-type: text/markdown; charset=utf-8 x-credits-charged: 1 x-route: http/datacenter x-hops: [{"rung":"h:dc","identity":"chrome","ms":412}] x-request-id: 01J8Z3K6W2M4Q9T7B5N1C0XHDEHeader What it tells you X-Credits-ChargedWhat this request cost. Here, 1 credit. X-RouteThe engine and proxy tier that delivered the page. X-HopsEach try, in order, as a JSON array: [{"rung":"h:dc","identity":"chrome","ms":412,"outcome":"ok"}]is one HTTP try on datacenter, as Chrome, 412 ms. Tries that ended in a block we detected cost 0.X-BillingOnly on a 422 blocked:blocked. You paid nothing.X-Request-IdThe id of this request. Quote it when you write to support. A
200is a page you paid for. When the site blocks every route we try, the answer is HTTP422witherror.codeblockedandX-Billing: blocked, and it costs nothing. Any other error is also JSON witherror.codeanderror.message. Troubleshooting has the fix for each one. -
Connect your AI agent (3 minutes)
The MCP server is
https://mcp.megalania.io. Pick your client:claude mcp add --transport http megalania https://mcp.megalania.io
Settings > Connectors > Add custom connector Name: Megalania URL: https://mcp.megalania.io Leave the client ID and client secret empty.
Add a custom connector (MCP server) in ChatGPT's settings. URL: https://mcp.megalania.io Authentication: OAuth. Leave the client ID and client secret empty.
{ "mcpServers": { "megalania": { "url": "https://mcp.megalania.io", "headers": { "Authorization": "Bearer meg_sk_your_key_here" } } } }Claude Code, Claude.ai and ChatGPT open a Megalania tab the first time a tool runs: sign in, check the account, and press Approve. You copy no key. In Claude Code, type
/mcpand pickmegalaniato start that sign-in. Cursor reads a key from~/.cursor/mcp.json, as above.Then ask your agent:
PromptUse megalania to fetch https://lab.megalania.io/cards and list the mug names and prices.
The agent calls
scrapeand answers from the page. A blocked page or an error costs nothing. MCP for agents lists every tool and the VS Code setup. -
Run one batch (3 minutes)
A batch takes up to 10,000 URLs in one call and runs them without a connection held open. It lives on the API host,
api.megalania.io, not onget.. This one fetches three pages of our Lab as Markdown, waits for them, and saves each result:API=https://api.megalania.io BATCH_ID=$(curl -sS -X POST "$API/v1/batches" \ -H "Authorization: Bearer $MEG_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid)" \ -d '{"urls": ["https://lab.megalania.io/paged?page=1", "https://lab.megalania.io/paged?page=2", "https://lab.megalania.io/paged?page=3"], "response_types": "markdown"}' | jq -r .id) echo "batch $BATCH_ID" until curl -sS -H "Authorization: Bearer $MEG_API_KEY" "$API/v1/batches/$BATCH_ID" | jq -e '.status | IN("queued", "running") | not' >/dev/null; do sleep 3; done curl -sS -H "Authorization: Bearer $MEG_API_KEY" "$API/v1/batches/$BATCH_ID/items" | jq -r '.items[] | [.position, .status, .credits_charged, (.result_url // "")] | @tsv' | while IFS=$'\t' read -r pos status credits url; do echo "item $pos: $status, $credits credits" [ -n "$url" ] && curl -sS -o "item-$pos.md" "$url" done# pip install requests import os import time import uuid import requests API = "https://api.megalania.io" auth = {"Authorization": f"Bearer {os.environ['MEG_API_KEY']}"} batch = requests.post( f"{API}/v1/batches", headers={**auth, "Idempotency-Key": str(uuid.uuid4())}, json={ "urls": [ "https://lab.megalania.io/paged?page=1", "https://lab.megalania.io/paged?page=2", "https://lab.megalania.io/paged?page=3", ], "response_types": "markdown", }, timeout=30, ) batch.raise_for_status() batch_id = batch.json()["id"] print("batch", batch_id) while requests.get(f"{API}/v1/batches/{batch_id}", headers=auth, timeout=30).json()["status"] in ("queued", "running"): time.sleep(3) items = requests.get(f"{API}/v1/batches/{batch_id}/items", headers=auth, timeout=30).json()["items"] for item in items: print(f"item {item['position']}: {item['status']}, {item['credits_charged']} credits") if item["result_url"]: with open(f"item-{item['position']}.md", "w", encoding="utf-8") as f: f.write(requests.get(item["result_url"], timeout=30).text)import { writeFile } from "node:fs/promises"; const API = "https://api.megalania.io"; const auth = { Authorization: `Bearer ${process.env.MEG_API_KEY}` }; const get = async (path) => (await fetch(API + path, { headers: auth })).json(); const res = await fetch(`${API}/v1/batches`, { method: "POST", headers: { ...auth, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ urls: ["https://lab.megalania.io/paged?page=1", "https://lab.megalania.io/paged?page=2", "https://lab.megalania.io/paged?page=3"], response_types: "markdown", }), }); if (!res.ok) throw new Error(`${res.status} ${await res.text()}`); const { id } = await res.json(); console.log("batch", id); while (["queued", "running"].includes((await get(`/v1/batches/${id}`)).status)) { await new Promise((r) => setTimeout(r, 3000)); } for (const item of (await get(`/v1/batches/${id}/items`)).items) { console.log(`item ${item.position}: ${item.status}, ${item.credits_charged} credits`); if (item.result_url) await writeFile(`item-${item.position}.md`, await (await fetch(item.result_url)).text()); }Nothing is charged when you submit. Each URL is priced and charged when a worker reaches it.
result_urlis a signed link that works for 15 minutes and takes no key. The cURL tab needsjq; save the Node.js tab asbatch.mjsand runnode batch.mjs(Node 20 or newer). Batches covers crawls, webhooks and paging. -
What it cost
4credits, if every page took the cheapest route. One for step 2 and one for each batch page. The MCP call in step 3 costs the same as a fetch. Blocks we detect and errors are free.
Bigger pages, a residential exit or a real browser cost more. Credits and pricing has the table.
Next steps
- Fetch, extract and lists: fields as JSON with CSS rules in
extract. - Troubleshooting: a symptom, its cause and the fix.
- Monitors: watch a page on a schedule.
- Error codes: every code, its price and its fix.
When the beta credits run out
The beta is free. When your credits or the beta limit run out, the answer is
402 insufficient_credits or 429 period_cost_cap. Write to
[email protected] from your account’s email, and we add more by hand.
Report a problem
Open https://app.megalania.io/report, or Help, then Report a
problem in the dashboard. Send the X-Request-Id of the request, and what
you expected and what you got. Do not send your key.
We never need it.