# Extract every link from any page

> Get every link on a web page as a JSON list of absolute URLs, with one API call. Build crawlers, audits and agents that navigate. $0.001 per page.

Send a URL and get back a JSON array of every link on the page, as absolute URLs. The building block for crawlers, sitemap checks and agents that need to know where to go next.

- $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, every link

With unwrap=true the response body is the JSON array itself.

- Absolute URLs, ready to fetch
- From the final page, after redirects
- Combine with markdown in one request

### cURL

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

### Python

```python
import os
import requests

response = requests.get(
    "https://api.grabber.sh/fetch",
    params={"url": "https://example.com/", "formats": "links", "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/', formats: 'links', 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/"}, "formats": {"links"}, "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/', 'formats' => 'links', '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

```json
[
  "https://example.com/pricing",
  "https://example.com/docs",
  "https://example.com/blog",
  "https://example.com/blog/rag-guide",
  "https://github.com/example"
]
```

## How it works

1. **Send the URL.** Call `GET /fetch` with `url` and `formats=links`.
2. **Grabber reads the page.** It follows redirects, loads the page and collects every link on it as an absolute URL.
3. **Decide what is next.** Filter the list, then fetch the pages you want. Each fetch is its own request.

## What people build with it

### Crawlers

Discover pages one level at a time and decide yourself which ones to follow.

### SEO audits

Check internal links, find pages that nothing links to, and spot links to old domains.

### Agents that navigate

Let an agent see the links on a page so it can choose the next one to read.

### Monitoring

Watch a listing or changelog page and act when a new link appears.

## 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

### Are relative links turned into full URLs?

Yes. Every link comes back as an absolute URL, so you can fetch it as it is.

### Does Grabber crawl the links for me?

No. Grabber loads one page per request, so you stay in control of what is fetched and what it costs. Fetch the next pages yourself, up to 60 requests per minute per key.

### Can I get the links and the content together?

Yes. Ask for formats=markdown,links and you get both in the JSON envelope, for $0.001.

### What about links that JavaScript adds?

Add js_render=true and the links are read after the page has run in a headless browser, for $0.005 a page.

## Related

- [URL to Markdown](https://grabber.sh/url-to-markdown): Clean Markdown for LLMs and RAG.
- [Metadata extractor](https://grabber.sh/metadata-extractor): Title, Open Graph tags, JSON-LD and more.
- [JavaScript rendering](https://grabber.sh/javascript-rendering): Pages built in the browser, rendered first.
- [All parameters](https://grabber.sh/docs/parameters): Every option of GET /fetch.

## 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)
