https://txtfetch.com/extract/html/
Any web page, fetched and reduced to clean text.
Pass a URL, not a file. txtfetch fetches the page server-side and hands back clean text, with the markup, scripts, and styles gone. Deciding what's chrome (nav, ads, cookie banners) versus article is a caller-side call. See the free tool below to check yours.
the-problem
Turning a web page into usable text usually means standing up a scraper. You fetch the HTML yourself, strip scripts and styles, and guess at which <div> is the actual content versus navigation and ads. You also handle redirects and encoding along the way. That's infrastructure most teams don't want to own just to get plain text into a RAG index.
one-request-solution
Skip the fetch-and-strip pipeline. Pass a url parameter to txtfetch, and it retrieves the page server-side, runs it through Apache Tika's HTML parser, and returns clean plain text. No headless browser, no boilerplate code to maintain.
curl -X POST https://api.txtfetch.com/v1/extract \
-H "Authorization: Bearer $TXTFETCH_KEY" \
-F file=@landing-page.htmlimport os
import requests
with open("landing-page.html", "rb") as f:
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
files={"file": f},
)
print(r.json()["extracted_text"])import { readFile } from "node:fs/promises";
const file = new Blob([await readFile("landing-page.html")]);
const form = new FormData();
form.append("file", file, "landing-page.html");
const res = await fetch("https://api.txtfetch.com/v1/extract", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
body: form,
});
const { extracted_text } = await res.json();
console.log(extracted_text);package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
f, err := os.Open("landing-page.html")
if err != nil {
panic(err)
}
defer f.Close()
var body bytes.Buffer
writer := multipart.NewWriter(&body)
part, err := writer.CreateFormFile("file", "landing-page.html")
if err != nil {
panic(err)
}
if _, err := io.Copy(part, f); err != nil {
panic(err)
}
writer.Close()
req, err := http.NewRequest("POST", "https://api.txtfetch.com/v1/extract", &body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result extractResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
fmt.Println(result.ExtractedText)
}Or skip the download. Pass a url parameter and txtfetch fetches the document server-side:
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/blog/2024-annual-report" \
-H "Authorization: Bearer $TXTFETCH_KEY"import os
import requests
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
params={"url": "https://example.com/blog/2024-annual-report"},
)
print(r.json()["extracted_text"])const endpoint = new URL("https://api.txtfetch.com/v1/extract");
endpoint.searchParams.set("url", "https://example.com/blog/2024-annual-report");
const res = await fetch(endpoint, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
});
const { extracted_text } = await res.json();
console.log(extracted_text);package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
endpoint, err := url.Parse("https://api.txtfetch.com/v1/extract")
if err != nil {
panic(err)
}
q := endpoint.Query()
q.Set("url", "https://example.com/blog/2024-annual-report")
endpoint.RawQuery = q.Encode()
req, err := http.NewRequest("POST", endpoint.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result extractResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
fmt.Println(result.ExtractedText)
}{
"status": "success",
"extracted_text": "..."
}what-comes-back
That is the shape. This is the text. A real .html from the benchmark corpus, word-diffed against the raw parser output. Nothing here was written for this page. Every character comes from a committed fixture.
txtfetch Pricing Page (HTML)
raw parser output
Pricing
Turn any document into clean plain text over a simple HTTP API.
pricing tiers diagram
Plans
Plan Price Quota
Hobby $0 500 docs/mo
Developer $19 10,000 docs/mo
Scale $99 100,000 docs/mo
Questions? Use the contact form & skip the 'support' email.
the human-checked ideal
Pricing
Turn any document into clean plain text over a simple HTTP API.
pricing tiers diagram
Plans
Plan Price Quota
Hobby $0 500 docs/mo
Developer $19 10,000 docs/mo
Scale $99 100,000 docs/mo
Questions? Use the contact form & skip the 'support' email.See all ten documents, with the full explanation →
formats-covered
.html.htm.xhtml
faq
- How do I extract text from a web page URL?
- POST to https://api.txtfetch.com/v1/extract?url=<page-url> with your API key in the Authorization header. txtfetch fetches the page server-side and returns { "status": "success", "extracted_text": "..." }.
- Does it strip navigation, ads, and boilerplate?
- It strips markup, not boilerplate. Tika's HTML parser removes scripts, styles, and tags. But nav, footer, and cookie-banner text is still text, so it comes back in the response like any other paragraph. Deciding what's chrome versus article is a deliberate, caller-side step. See /tools/html-to-text for a free tool that shows you exactly what your pages' chrome looks like before you index them.
- Can I upload a local .html file instead of a URL?
- Yes. The same endpoint accepts a multipart file upload for local HTML files, same as any other format.
go-further
Web & data
Send a real .html through it.
One HTTP call returns the text. Read one in your browser first, for free.
Get an API key →