GET
/extractExtract clean content from a URL
Fetches the URL and returns the main article content, with navigation, scripts, styles and boilerplate removed.
Set format to markdown (default) to preserve headings, lists, code blocks and links; text for plain prose with no markup; or html for the cleaned HTML fragment. Page metadata — title, description, author, publication date, site name and language — is returned alongside the content when the page declares it.
$0.002 per call60 req/minFree allowance applies
Request
curl -X GET "https://www.twotic.dev/v1/web-extract/extract" \
-H "Authorization: Bearer $TWOTIC_KEY"const res = await fetch("https://www.twotic.dev/v1/web-extract/extract", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.TWOTIC_KEY}`,
},
})
if (!res.ok) throw new Error(await res.text())
const data = await res.json()
console.log(res.headers.get("X-Twotic-Cost"))import os, requests
res = requests.get(
"https://www.twotic.dev/v1/web-extract/extract",
headers={"Authorization": f"Bearer {os.environ['TWOTIC_KEY']}"},
)
res.raise_for_status()
data = res.json()
print(res.headers["X-Twotic-Cost"])package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://www.twotic.dev/v1/web-extract/extract", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("TWOTIC_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(string(out))
fmt.Println(res.Header.Get("X-Twotic-Cost"))
}<?php
$ch = curl_init("https://www.twotic.dev/v1/web-extract/extract");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("TWOTIC_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($data);require "net/http"
require "json"
uri = URI("https://www.twotic.dev/v1/web-extract/extract")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('TWOTIC_KEY')}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(req)
end
puts JSON.parse(res.body)
puts res["X-Twotic-Cost"]{
"mcpServers": {
"web-extract": {
"type": "http",
"url": "https://www.twotic.dev/api/mcp/web-extract",
"headers": { "Authorization": "Bearer tk_live_your_key" }
}
}
}Parameters
query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| url | string | required | The absolute URL to extract. Must be publicly reachable http or https.e.g. https://example.com/blog/post |
| format | string | optional | Output format. Defaults to markdown.one of: markdown · text · htmle.g. markdown |
Response
200The extracted content and page metadata.
{
"url": "https://example.com/blog/post",
"title": "How we cut inference cost by 80%",
"byline": "Dana Whitfield",
"format": "markdown",
"content": "## The problem\n\nOur inference bill grew faster than usage did…",
"language": "en",
"siteName": "Example Engineering",
"wordCount": 1840,
"description": "A write-up of the changes that mattered.",
"publishedAt": "2026-06-14T09:00:00Z"
}400The url is missing, malformed, or resolves to a private address.
{
"error": "blocked_host",
"message": "That URL resolves to a private or reserved address, which cannot be fetched."
}422The target returned an error status.
{
"error": "target_error",
"message": "The target returned HTTP 404. Check the URL is publicly reachable."
}As an agent tool
Connect https://www.twotic.dev/api/mcp/web-extract and this endpoint is exposed as the tool web-extract_extract.
Fetch a web page and return its main article content as clean Markdown, stripped of navigation, ads and scripts. Choose this whenever you need to READ the content of a URL — to summarise it, answer questions about it, or store it for retrieval. Requires `url`; optional `format` of markdown, text or html. Returns the content plus title, description, author, published date and word count. Use the links tool instead if you only need the page's outbound URLs.