How to Convert Markdown to HTML with an API (cURL, Node.js, Python, Go)
By VeloForge Labs · · 3 min read
Most apps end up needing Markdown-to-HTML conversion sooner or later: a comment box, a help center, release notes, a CMS field. You can bundle a parser into every service that needs one, or you can call a single HTTP endpoint and get HTML back. This guide covers the second approach and shows what a request and response look like in four languages.
When an API makes sense
A Markdown library is the right answer when you convert at build time or in a single codebase. An API is a better fit when:
- several services, written in different languages, all need identical output;
- you run in a runtime where heavy HTML-sanitizing libraries are awkward (edge functions, serverless, low-memory containers);
- you want the parser and the sanitizer updated in one place instead of in five repositories.
The trade-off is a network hop. For static content, convert once and cache the HTML. For user-generated content, convert on write and store the result, so reads stay fast.
The request
TexToolsAI exposes one endpoint: POST /api/convert. You send JSON with a markdown string and an optional options object. Authentication is a Bearer token in the Authorization header.
curl -X POST https://texttoolsai.org/api/convert \
-H "Authorization: Bearer tt_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"markdown": "# Hello\n\n**Bold text**", "options": {"gfm": true}}'
The only option is gfm, which turns GitHub-Flavored Markdown on or off. It defaults to on, so tables, task lists and strikethrough work without extra setup.
The response
A successful call returns 200 with the HTML and a little metadata:
{
"success": true,
"html": "<h1>Hello</h1>\n<p><strong>Bold text</strong></p>\n",
"meta": { "latency_ms": 3.42, "sanitized": true }
}
The html field has already been through a sanitizer, so you can put it in a page without a second cleaning pass. See why that matters if you are wondering what "sanitized" actually protects you from.
Node.js
Node 18 and newer have fetch built in, so no dependency is needed.
async function markdownToHtml(markdown) {
const res = await fetch("https://texttoolsai.org/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + process.env.TEXTOOLSAI_API_KEY,
},
body: JSON.stringify({ markdown, options: { gfm: true } }),
});
const data = await res.json();
if (!res.ok || !data.success) throw new Error(data.error || "Conversion failed");
return data.html;
}
Keep the key in an environment variable. Never ship it to a browser: anyone who opens developer tools can read it.
Python
import os
import requests
def markdown_to_html(markdown: str) -> str:
response = requests.post(
"https://texttoolsai.org/api/convert",
json={"markdown": markdown, "options": {"gfm": True}},
headers={"Authorization": "Bearer " + os.environ["TEXTOOLSAI_API_KEY"]},
timeout=10,
)
response.raise_for_status()
return response.json()["html"]
Always set a timeout. Without one, requests can wait forever on a stalled connection. There is a longer Python walkthrough in Markdown to HTML in Python.
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]any{
"markdown": "# Hello\n\n**Bold text**",
"options": map[string]any{"gfm": true},
})
req, _ := http.NewRequest("POST", "https://texttoolsai.org/api/convert", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("TEXTOOLSAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var out struct {
HTML string `json:"html"`
}
json.NewDecoder(res.Body).Decode(&out)
fmt.Println(out.HTML)
}
Try it without a key
The playground on the home page calls the same endpoint with a demo header, limited to 100 requests per day and 25 KB per request. It is the quickest way to see how your own Markdown renders before you write any code.
Production checklist
- Convert on write for user content and store the HTML, instead of converting on every page view.
- Handle non-200 responses. Read how to handle API errors and rate limits before you ship.
- Keep your API key server-side.
- Check the full API reference for the exact error codes.