# Turn any URL into clean Markdown

> Convert any web page or PDF into clean Markdown with one API call, ready for LLMs, RAG and AI agents. $0.001 per page, no subscription, errors free.

Send a URL and get the content back as Markdown. Headings, lists, tables, links and code come through; scripts, styles and tag soup do not. Ready for a prompt, a vector store or an agent.

- $1 free credit, no card
- No subscription
- Failed requests are free

[Get API key](https://dashboard.grabber.sh/signup) · [Read the docs](https://grabber.sh/docs/parameters)

## One request, clean Markdown

Add unwrap=true and the Markdown is the whole response body, with Content-Type: text/markdown.

- Works on HTML pages and PDFs
- Follows redirects to the final page
- Add links or metadata in the same request

### cURL

```bash
curl -G https://api.grabber.sh/fetch \
  -H "Authorization: Bearer $GRABBER_API_KEY" \
  --data-urlencode "url=https://example.com/blog/rag-guide" \
  -d "formats=markdown" \
  -d "unwrap=true"
```

### Python

```python
import os
import requests

response = requests.get(
    "https://api.grabber.sh/fetch",
    params={"url": "https://example.com/blog/rag-guide", "formats": "markdown", "unwrap": "true"},
    headers={"Authorization": f"Bearer {os.environ['GRABBER_API_KEY']}"},
    timeout=130,
)
response.raise_for_status()
print(response.text)
```

### Node.js

```javascript
const params = new URLSearchParams({ url: 'https://example.com/blog/rag-guide', formats: 'markdown', unwrap: 'true' })

const response = await fetch(`https://api.grabber.sh/fetch?${params}`, {
  headers: { Authorization: `Bearer ${process.env.GRABBER_API_KEY}` },
  signal: AbortSignal.timeout(130_000),
})
if (!response.ok) throw new Error(`Grabber answered ${response.status}`)
console.log(await response.text())
```

### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"time"
)

func main() {
	query := url.Values{"url": {"https://example.com/blog/rag-guide"}, "formats": {"markdown"}, "unwrap": {"true"}}
	req, _ := http.NewRequest("GET", "https://api.grabber.sh/fetch?"+query.Encode(), nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("GRABBER_API_KEY"))

	client := &http.Client{Timeout: 130 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status)
	fmt.Println(string(body))
}
```

### PHP

```php
<?php
$query = http_build_query(['url' => 'https://example.com/blog/rag-guide', 'formats' => 'markdown', 'unwrap' => 'true']);

$ch = curl_init("https://api.grabber.sh/fetch?$query");
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('GRABBER_API_KEY')],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 130,
]);
$body = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), "\n", $body;
```

### Response body

```markdown
# A practical guide to RAG

Retrieval-augmented generation answers questions from your own documents.

## 1. Split pages into chunks

- Keep each heading with its text
- Aim for 300 to 800 tokens per chunk

| Chunk size | Recall |
| --- | --- |
| 300 tokens | 0.81 |

[Next: choosing embeddings](https://example.com/blog/embeddings)
```

## How it works

1. **Send the URL.** Call `GET /fetch` with `url` and `formats=markdown`. Add `unwrap=true` to get the Markdown as the body.
2. **Grabber loads the page.** It follows redirects, reads the HTML or the PDF, and converts the content to Markdown.
3. **Use the Markdown.** Put it in a prompt, split it into chunks for a vector store, or save it. `X-Grabber-Cost` says what it cost.

## What people build with it

### RAG pipelines

Index documentation, help centers and articles as Markdown, so chunks keep their headings and tables.

### Agents that browse

Give an agent a tool that reads a page in a few thousand tokens instead of tens of thousands of HTML.

### Docs for coding assistants

Feed the current docs of a library to Cursor or Claude, so they code against the version you use.

### Content migration

Move pages from an old site into a Markdown-based CMS or a static site generator.

## Pricing

Prepaid credit, taken one request at a time. Ask for several formats in one request at the price of one.

| Request | Price |
| --- | --- |
| A page | **$0.001** |
| A page with `js_render=true` | **$0.005** |
| Any error | $0 |
| Credit when you sign up | $1, about 1,000 pages |

## Questions

### Why Markdown instead of HTML for an LLM?

Markdown keeps the structure a model needs, such as headings, lists, tables and links, and drops the markup it does not. The same page is usually several times smaller, so it costs fewer tokens and leaves more room in the context window.

### Does it work with PDFs?

Yes. Point url at a PDF and you get its text back as Markdown, at the same price as a web page.

### Can I get Markdown and links in one request?

Yes. Ask for formats=markdown,links and both come back in the JSON envelope. It is one page load, so it costs $0.001, the same as one format.

### What if the page is built with JavaScript?

Add js_render=true. The page runs in a headless browser first, and the Markdown is made from what it shows. A rendered page costs $0.005.

## Related

- [HTML to text](https://grabber.sh/html-to-text): Plain text with no markup at all.
- [JavaScript rendering](https://grabber.sh/javascript-rendering): Pages built in the browser, rendered first.
- [Link extractor](https://grabber.sh/link-extractor): Every link on a page, as absolute URLs.
- [MCP server](https://grabber.sh/mcp): The same API as a tool for your agent.

## Give your agents the web

Sign up in a minute and fetch your first 1,000 pages for free.

[Get API key](https://dashboard.grabber.sh/signup) · [Read the docs](https://grabber.sh/docs)
