HTML to TXT API
POST /v2/convert/html/to/txt returns the page's text as UTF-8, wrapped at 100 characters unless you set LineWidth. The sample used LineWidth=72: 41 lines, none longer than 72 characters, with the table drawn in box-drawing characters and both links listed as numbered references at the end.
- Endpoint
- POST /v2/
convert/ html/ to/ txt - Accepts
- html
- Sample timing
- 1 ms median of 5 runsHow we measure
- Request size
- Up to 10 MB on the Free plan or 100 MB on paid plans, all files together
Request and response
Every sample below ran against the API before this page was published. Set PDFCONVERSIONAPI_KEY to your key and run it as is.
curl -sS -X POST \
https://api.pdfconversionapi.com/v2/convert/html/to/txt \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@seed-swap.html \
--form-string LineWidth=72 \
-o response.json
# FileData is base64. Save the first file in converted/,
# or print the JSON error.
if jq -e '.Files' response.json > /dev/null; then
mkdir -p converted
name=$(jq -r '.Files[0].FileName' response.json)
jq -r '.Files[0].FileData' response.json \
| base64 --decode > "converted/$name"
else
cat response.json
fiimport base64
import os
import requests
key = os.environ["PDFCONVERSIONAPI_KEY"]
response = requests.post(
"https://api.pdfconversionapi.com/v2/convert/html/to/txt",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("seed-swap.html", "rb"))],
data={
"LineWidth": "72",
},
timeout=180,
)
result = response.json()
if not response.ok:
raise SystemExit(f"{result['Code']}: {result['Message']}")
os.makedirs("converted", exist_ok=True)
for file in result["Files"]:
path = os.path.join("converted", file["FileName"])
with open(path, "wb") as out:
out.write(base64.b64decode(file["FileData"]))
print(path, file["FileSize"], "bytes")
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
const form = new FormData();
const file = "seed-swap.html";
form.append("File", new Blob([await readFile(file)]), file);
form.append("LineWidth", "72");
const url = "https://api.pdfconversionapi.com/v2/convert/html/to/txt";
const key = process.env.PDFCONVERSIONAPI_KEY;
const response = await fetch(url, {
method: "POST",
headers: { Authorization: `Bearer ${key}` },
body: form,
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${result.Code}: ${result.Message}`);
}
await mkdir("converted", { recursive: true });
for (const file of result.Files) {
const path = join("converted", file.FileName);
await writeFile(path, Buffer.from(file.FileData, "base64"));
console.log(path, file.FileSize, "bytes");
}
{
"ConversionCost": 1,
"ConversionTime": 0.001,
"Files": [
{
"FileName": "seed-swap.txt",
"FileExt": "txt",
"FileSize": 2176,
"FileData": "IyBTcHJpbmcgc2VlZCBzd2Fw…"
}
]
}Response from our test run on 2026-11-03. ConversionTime shows the median of 5 runs. FileData is shortened here; the real response carries the whole file as base64.
The sample, converted
The same file the code sends. Download the input and the output and compare them yourself.
seed-swap.txt, first 30 of 41 lines
# Spring seed swap 2027The **Maple Row Seed Library** is a fictional lending library for gardenseeds. Bring seeds you saved, take seeds you want, and *return a packet*after harvest. Read the [borrowing rules][1] before you come.Doors open at 10:00[A kraft seed packet with three seeds]## How the swap works1. Check in at the front table and get a tally card.2. Label each packet with the variety and the year it was saved.3. Take up to **five packets** per household.## Packets on hand───────────────┬─────────┬───────┬───────────┬───────────Variety │Crop │Packets│Germination│Last tested───────────────┼─────────┼───────┼───────────┼───────────Cherokee Purple│Tomato │42 │91% │2027-01-14 ───────────────┼─────────┼───────┼───────────┼───────────Dragon Tongue │Bush bean│18 │86% │2027-01-21 ───────────────┼─────────┼───────┼───────────┼───────────Lemon Queen │Sunflower│27 │78% │2026-12-03 ───────────────┼─────────┼───────┼───────────┼───────────Red Russian │Kale │9 │94% │2027-02-02 ───────────────┴─────────┴───────┴───────────┴───────────## What to bring
- Input
- seed-swap.html (3.0 KB)
- Output
- seed-swap.txt (2.1 KB)
- Source
- A one-page web page for a fictional community seed library, written for this site: headings, a table, two lists, links, a quote, a style sheet, a script and an inlined picture. (CC0-1.0). How it was made
- Made by
- 2026-11-04, API build
9eeeb0640aba
Parameters
Send these as form fields next to the file. Names are case-insensitive. If you set one of the documented options below that we don't support yet, the request fails with a 400 that names it instead of returning a file made without it.
| Parameter | What it does |
|---|---|
LineWidthinteger, default 100 | Column at which text wraps. The sample's paragraphs wrap at 72. Narrower than a table, the table's cells wrap inside their columns: at 20, "Cherokee Purple" took five lines.Values: 20–1000 |
FileNamestring | Base name of the .txt; the sample's is seed-swap.txt. |
StoreFileboolean, default false | true returns a 3-hour link in Files[].Url instead of the text inline. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
JavaScript | Scripts never run. The default true is accepted; false returns 400. |
Url | Send the page as a file. A Url value returns 400 "Url is not supported yet for HTML → TXT". |
CssMediaType | CSS is not applied, so only the default screen is accepted. |
ExtractElements | Any selector returns 400; the whole body is converted. |
HideElements | Any selector returns 400. Remove the elements from the HTML before sending it. |
ConversionDelay | Only 0 passes. |
UserCss | Refused, like UserJs, Cookies, Headers, AuthUsername, AuthPassword, AdBlock, CookieConsentBlock and WaitElement, which all belong to loading a page in a browser. |
What carries over, and what doesn't
Kept
- Headings marked with
#and##, bold with**and italic with* - The table in aligned columns, drawn with │, ─ and ┼, each column as wide as its longest cell
- Numbered steps as
1.to3., bullets as*, the nested bullet indented two spaces - Links as
[text][1], with the URLs listed as[1]: https://seeds.example/rulesat the end - The picture's alt text in brackets:
[A kraft seed packet with three seeds] - The quote with
>on each wrapped line - Strikethrough as combining strokes (s̶t̶r̶i̶k̶e̶) and superscript marked with
^and braces
Lost or not yet supported
- Everything in the
<head>: the title is not printed. - Script output, styles and comments.
- Charset declarations. A windows-1252 page with a matching meta tag came back with U+FFFD in place of é, so send UTF-8.
- Horizontal rules, which leave only a blank line, and the subscript mark.
- Windows line endings. Lines end with LF only, and there is no option to change that.
Limits
- One HTML file per request.
- Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together.
- 120 seconds per conversion, then 504.
Where teams use it
Plain-text parts of HTML emails
A multipart email should carry a text version next to the HTML one. Convert the HTML body with LineWidth=72 and the links end up as numbered references a text-only mail client can show.
Text for search indexes and diffs
Index the words of a page without its tags, or compare two versions of a page line by line. Tables stay aligned in columns, so row values remain readable in a diff.
Questions
Is the output plain text or Markdown?
Plain text with light markers that read naturally: # before headings, ** around bold, * bullets and numbered link references. It is not meant to be parsed as Markdown. For real Markdown, use /v2/convert/html/to/md.
How do I keep long lines unwrapped?
Set LineWidth=1000, the highest value. At 1000 the sample's opening paragraph stays on one 207-character line and the file has 38 lines instead of 41 at 72. The size hardly moves (2,174 bytes against 2,176), since a wrap only turns a space into a line break.
Can I convert a web address directly?
No. Upload the HTML as a file. ConvertAPI's Url option, and the other browser options such as JavaScript=false or WaitElement, return 400 because nothing is loaded or run.
What happens to a table that is wider than LineWidth?
The columns are squeezed and cell text wraps inside them, breaking words if it must. At LineWidth=20 the sample's header "Variety" split into "Var", "iet" and "y".
Convert your first HTML file in a minute.