Fetch
curl --request GET \
--url https://api.keenable.ai/v1/fetch \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.keenable.ai/v1/fetch"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.keenable.ai/v1/fetch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.keenable.ai/v1/fetch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.keenable.ai/v1/fetch"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.keenable.ai/v1/fetch")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.keenable.ai/v1/fetch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"url": "<string>",
"title": "<string>",
"description": "<string>",
"author": "<string>",
"content": "<string>",
"published_at": 123
}API reference
Fetch
Fetch webpage contents
GET
/
v1
/
fetch
Fetch
curl --request GET \
--url https://api.keenable.ai/v1/fetch \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.keenable.ai/v1/fetch"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.keenable.ai/v1/fetch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.keenable.ai/v1/fetch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.keenable.ai/v1/fetch"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.keenable.ai/v1/fetch")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.keenable.ai/v1/fetch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"url": "<string>",
"title": "<string>",
"description": "<string>",
"author": "<string>",
"content": "<string>",
"published_at": 123
}Retrieve content from a URL in markdown format.
Part of the API reference, which covers the base URL, authentication, and the limits both endpoints share.
curl "https://api.keenable.ai/v1/fetch?url=https://example.com/ts-best-practices" \
-H "X-API-Key: keen_<your_key>"
import requests
r = requests.get(
"https://api.keenable.ai/v1/fetch",
headers={"X-API-Key": "keen_<your_key>"},
params={"url": "https://example.com/ts-best-practices"},
)
print(r.json()["content"])
const url = "https://example.com/ts-best-practices";
const r = await fetch(
`https://api.keenable.ai/v1/fetch?url=${encodeURIComponent(url)}`,
{ headers: { "X-API-Key": "keen_<your_key>" } },
);
const { content } = await r.json();
By default, only URLs that Keenable indexes are supported, and attempting to fetch a document that is not indexed results in an error. Pass
live=true to fetch directly from the source, including URLs that are not indexed.Without a key
GET /v1/fetch/public takes the same query parameters and returns the same shape, with no API key:
curl "https://api.keenable.ai/v1/fetch/public?url=https://example.com/ts-best-practices" \
-H "X-Keenable-Title: My App"
X-Keenable-Title names your application and is required on the public endpoint; without it the request is rejected with 400 Missing app identifier. Keyless calls are rate limited per IP and consume no credits — see Authentication for the details. The playground on this page calls the keyed endpoint.
Request
string
required
URL to fetch.
integer
default:"50000"
Maximum number of characters of content to return. Longer content is truncated.
boolean
default:"false"
Fetch the page live from the source instead of returning Keenable’s indexed copy. Enables fetching URLs that are not indexed.
string
Optional extraction instruction, at most 2000 characters. When set, an LLM reads the fetched page and
content contains only the output for this instruction instead of the full page. Example: List all pricing tiers with their monthly prices.Response
string
The fetched URL.
string
Page title (if available).
string
Short summary of the page (if available).
string
Page author (if available).
string
Extracted page content in markdown.
integer
Publication time as a Unix timestamp in seconds (if available).
Example
{
"url": "https://example.com/ts-best-practices",
"title": "TypeScript Best Practices 2026",
"description": "A comprehensive guide to modern TypeScript patterns and best practices.",
"author": "Jane Doe",
"published_at": 1768435200,
"content": "# TypeScript Best Practices 2026\n\nUse strict mode, prefer interfaces over type aliases for object shapes..."
}