MegalaniaDocs
Docs menu
  1. Docs
  2. Start
  3. Quickstart
Start

Quickstart

llms.txtUpdated 8 Nov 2026

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.

  1. Get a key (2 minutes)

    Open https://app.megalania.io/login and 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:

    Shell
    export MEG_API_KEY='meg_sk_your_key_here'

    Send the key in the Authorization header only. A key in a URL is refused with 401 bad_token. A new key works within a second, at most a minute. Get a key has the details.

  2. 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 headers
    HTTP/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: 01J8Z3K6W2M4Q9T7B5N1C0XHDE
    Header What it tells you
    X-Credits-Charged What this request cost. Here, 1 credit.
    X-Route The engine and proxy tier that delivered the page.
    X-Hops Each 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-Billing Only on a 422 blocked: blocked. You paid nothing.
    X-Request-Id The id of this request. Quote it when you write to support.

    A 200 is a page you paid for. When the site blocks every route we try, the answer is HTTP 422 with error.code blocked and X-Billing: blocked, and it costs nothing. Any other error is also JSON with error.code and error.message. Troubleshooting has the fix for each one.

  3. 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 /mcp and pick megalania to start that sign-in. Cursor reads a key from ~/.cursor/mcp.json, as above.

    Then ask your agent:

    Prompt
    Use megalania to fetch https://lab.megalania.io/cards and list the mug names and prices.

    The agent calls scrape and answers from the page. A blocked page or an error costs nothing. MCP for agents lists every tool and the VS Code setup.

  4. 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 on get.. 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_url is a signed link that works for 15 minutes and takes no key. The cURL tab needs jq; save the Node.js tab as batch.mjs and run node batch.mjs (Node 20 or newer). Batches covers crawls, webhooks and paging.

  5. What it cost

    4

    credits, 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.

Try it in the PlaygroundRun the same request in your browser and watch each try. No code needed.Open in Playground

Next steps

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.