2 creditsPDF to HTML API — structure preserved
Responsive semantic HTML or pixel-faithful fixed layout — your choice per request.
PDF to HTML converts a PDF into web-ready HTML in one REST call. Responsive mode rebuilds the content as semantic markup — h1–h6, paragraphs, lists, tables and images — that reflows on any screen; fixed mode preserves absolute positioning for visual fidelity. Headings, tables, lists and links survive the conversion. Two credits per document.
How does the PDF to HTML API work?
One HTTP request from any language. Every ASHDOCS endpoint uses the same X-API-Key header.
curl -X POST https://www.ashdocs.com/api/v1/tools/pdf-to-html \
-H "X-API-Key: ash_live_..." \
-F "files=@annual-report.pdf" \
-F 'options={"mode":"responsive","inline_images":true}'import requests
r = requests.post(
"https://www.ashdocs.com/api/v1/tools/pdf-to-html",
headers={"X-API-Key": "ash_live_..."},
files=[("files", open("annual-report.pdf", "rb"))],
data={"options": '{"mode":"responsive","inline_images":true}'},
)
job = r.json()
print(job["status"], job["output_files"][0]["url"])import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("files", new Blob([await readFile("annual-report.pdf")]), "annual-report.pdf");
form.append("options", JSON.stringify({"mode":"responsive","inline_images":true}));
const res = await fetch("https://www.ashdocs.com/api/v1/tools/pdf-to-html", {
method: "POST",
headers: { "X-API-Key": "ash_live_..." },
body: form,
});
const job = await res.json();
console.log(job.status, job.output_files[0].url);using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "ash_live_...");
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(await File.ReadAllBytesAsync("annual-report.pdf")), "files", "annual-report.pdf");
form.Add(new StringContent("{\"mode\":\"responsive\",\"inline_images\":true}"), "options");
var res = await client.PostAsync("https://www.ashdocs.com/api/v1/tools/pdf-to-html", form);
var job = await res.Content.ReadAsStringAsync();
Console.WriteLine(job);import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class Sample {
static final String BOUNDARY = "AshdocsBoundary7MA4YWxkTrZu0gW";
public static void main(String[] args) throws Exception {
ByteArrayOutputStream body = new ByteArrayOutputStream();
addFile(body, "files", "annual-report.pdf");
addField(body, "options", "{\"mode\":\"responsive\",\"inline_images\":true}");
body.write(("--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8));
HttpRequest req = HttpRequest.newBuilder(URI.create("https://www.ashdocs.com/api/v1/tools/pdf-to-html"))
.header("X-API-Key", "ash_live_...")
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
.POST(HttpRequest.BodyPublishers.ofByteArray(body.toByteArray()))
.build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
static void addFile(ByteArrayOutputStream body, String name, String path) throws Exception {
body.write(("--" + BOUNDARY + "\r\nContent-Disposition: form-data; name=\"" + name + "\"; filename=\""
+ Path.of(path).getFileName() + "\"\r\nContent-Type: application/octet-stream\r\n\r\n").getBytes(StandardCharsets.UTF_8));
body.write(Files.readAllBytes(Path.of(path)));
body.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
static void addField(ByteArrayOutputStream body, String name, String value) throws Exception {
body.write(("--" + BOUNDARY + "\r\nContent-Disposition: form-data; name=\"" + name + "\"\r\n\r\n"
+ value + "\r\n").getBytes(StandardCharsets.UTF_8));
}
}#include <stdio.h>
#include <curl/curl.h>
int main(void) {
CURL *curl = curl_easy_init();
if (!curl) return 1;
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "X-API-Key: ash_live_...");
curl_mime *mime = curl_mime_init(curl);
curl_mimepart *part;
part = curl_mime_addpart(mime);
curl_mime_name(part, "files");
curl_mime_filedata(part, "annual-report.pdf");
part = curl_mime_addpart(mime);
curl_mime_name(part, "options");
curl_mime_data(part, "{\"mode\":\"responsive\",\"inline_images\":true}", CURL_ZERO_TERMINATED);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
curl_easy_setopt(curl, CURLOPT_URL, "https://www.ashdocs.com/api/v1/tools/pdf-to-html");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode rc = curl_easy_perform(curl);
printf("\n");
curl_mime_free(mime);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return rc == CURLE_OK ? 0 : 1;
}Common use cases
- →Publishing PDF reports as indexable web pages
- →In-browser document viewers
- →Migrating legacy PDFs into a CMS
Frequently asked questions
Does the HTML look exactly like the PDF?+
In fixed mode, yes — page geometry is reproduced with absolute positioning. Responsive mode trades exact appearance for semantic HTML that reflows, indexes and works with screen readers.
Can I convert a scanned PDF to HTML?+
Run OCR first — a scan contains images of text, not text. Chain the /ocr endpoint before /pdf-to-html and the conversion works normally.
What happens to images inside the PDF?+
With inline_images enabled they are embedded as data URIs inside the returned HTML. Disabled, the response is a ZIP containing the HTML plus extracted image assets.
Do tables survive the conversion?+
Simple ruled tables convert to real <table> markup. Heavily merged or borderless tables are best extracted with /pdf-to-table instead and rendered from data.