Convert Markdown
Convert Mathpix Markdown (MMD) text to other formats like DOCX, XLSX, LaTeX, HTML, PDF, and PPTX.
info
See Conversion Formats for the full list with availability and descriptions.
Workflow
- Submit MMD text with desired formats — returns a
conversion_id - Poll status with
GET /v3/converter/{conversion_id} - Download results by appending the format extension:
GET /v3/converter/{conversion_id}.docx,.tex.zip, etc.
Submit a conversion
Submit Mathpix Markdown text to the v3/converter endpoint:
- mpxpy
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
from mpxpy.mathpix_client import MathpixClient
client = MathpixClient(app_id="APP_ID", app_key="APP_KEY")
conversion = client.conversion_new(
mmd="_full mmd text_",
convert_to_docx=True,
convert_to_tex_zip=True,
)
print(conversion.conversion_id)
curl -X POST https://api.mathpix.com/v3/converter \
-H 'app_id: APP_ID' \
-H 'app_key: APP_KEY' \
-H 'Content-Type: application/json' \
--data '{"mmd": "_full mmd text_", "formats": {"docx": true, "tex.zip": true}}'
import requests, json
r = requests.post("https://api.mathpix.com/v3/converter",
json={
"mmd": "_full mmd text_",
"formats": {"docx": True, "tex.zip": True}
},
headers={
"app_id": "APP_ID",
"app_key": "APP_KEY",
"Content-type": "application/json"
}
)
print(r.json()) # {"conversion_id": "..."}
const response = await fetch("https://api.mathpix.com/v3/converter", {
method: "POST",
headers: {
app_id: "APP_ID",
app_key: "APP_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
mmd: "_full mmd text_",
formats: { docx: true, "tex.zip": true },
}),
});
const { conversion_id } = await response.json();
console.log(`Conversion ID: ${conversion_id}`);
body := bytes.NewBufferString(`{
"mmd": "_full mmd text_",
"formats": {"docx": true, "tex.zip": true}
}`)
req, _ := http.NewRequest("POST", "https://api.mathpix.com/v3/converter", body)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result)) // {"conversion_id": "..."}
HttpClient client = HttpClient.newHttpClient();
String body = """
{
"mmd": "_full mmd text_",
"formats": { "docx": true, "tex.zip": true }
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/converter"))
.header("app_id", "APP_ID")
.header("app_key", "APP_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Example response
{
"conversion_id": "2024_01_15_abc123def456"
}
Use the conversion_id to poll conversion status and download results.
With conversion options
Customize the v3/converter output with format-specific options:
- Request body
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
{
"mmd": "_full mmd text_",
"formats": {"docx": true, "pdf": true},
"conversion_options": {
"docx": {
"font": "Times New Roman",
"fontSize": "28",
"orientation": "portrait"
},
"pdf": {
"fontSize": "14",
"text_color": "black",
"margin": "40"
}
}
}
curl -X POST https://api.mathpix.com/v3/converter \
-H 'app_id: APP_ID' \
-H 'app_key: APP_KEY' \
-H 'Content-Type: application/json' \
--data '{
"mmd": "_full mmd text_",
"formats": {"docx": true, "pdf": true},
"conversion_options": {
"docx": {"font": "Times New Roman", "fontSize": "28", "orientation": "portrait"},
"pdf": {"fontSize": "14", "text_color": "black", "margin": "40"}
}
}'
import requests, json
r = requests.post("https://api.mathpix.com/v3/converter",
json={
"mmd": "_full mmd text_",
"formats": {"docx": True, "pdf": True},
"conversion_options": {
"docx": {"font": "Times New Roman", "fontSize": "28", "orientation": "portrait"},
"pdf": {"fontSize": "14", "text_color": "black", "margin": "40"}
}
},
headers={
"app_id": "APP_ID",
"app_key": "APP_KEY",
"Content-type": "application/json"
}
)
print(r.json())
const response = await fetch("https://api.mathpix.com/v3/converter", {
method: "POST",
headers: {
app_id: "APP_ID",
app_key: "APP_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
mmd: "_full mmd text_",
formats: { docx: true, pdf: true },
conversion_options: {
docx: { font: "Times New Roman", fontSize: "28", orientation: "portrait" },
pdf: { fontSize: "14", text_color: "black", margin: "40" },
},
}),
});
const { conversion_id } = await response.json();
console.log(`Conversion ID: ${conversion_id}`);
body := bytes.NewBufferString(`{
"mmd": "_full mmd text_",
"formats": {"docx": true, "pdf": true},
"conversion_options": {
"docx": {"font": "Times New Roman", "fontSize": "28", "orientation": "portrait"},
"pdf": {"fontSize": "14", "text_color": "black", "margin": "40"}
}
}`)
req, _ := http.NewRequest("POST", "https://api.mathpix.com/v3/converter", body)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result))
HttpClient client = HttpClient.newHttpClient();
String body = """
{
"mmd": "_full mmd text_",
"formats": { "docx": true, "pdf": true },
"conversion_options": {
"docx": { "font": "Times New Roman", "fontSize": "28", "orientation": "portrait" },
"pdf": { "fontSize": "14", "text_color": "black", "margin": "40" }
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/converter"))
.header("app_id", "APP_ID")
.header("app_key", "APP_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Example response
{
"conversion_id": "2024_01_15_abc123def456"
}
See Conversion Options for all format-specific settings.
Poll conversion status
Poll GET v3/converter/{conversion_id} to check the status of each requested format:
- mpxpy
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
# wait_until_complete handles polling automatically
conversion.wait_until_complete(timeout=30)
print(conversion.conversion_status())
curl https://api.mathpix.com/v3/converter/CONVERSION_ID \
-H 'app_id: APP_ID' \
-H 'app_key: APP_KEY'
import requests, time
headers = {"app_id": "APP_ID", "app_key": "APP_KEY"}
conversion_id = "CONVERSION_ID"
while True:
r = requests.get(f"https://api.mathpix.com/v3/converter/{conversion_id}", headers=headers)
status = r.json()
print(status)
all_done = all(
v["status"] == "completed"
for v in status.get("conversion_status", {}).values()
)
if all_done:
break
time.sleep(3)
const headers = { app_id: "APP_ID", app_key: "APP_KEY" };
const conversionId = "CONVERSION_ID";
while (true) {
const response = await fetch(`https://api.mathpix.com/v3/converter/${conversionId}`, { headers });
const status = await response.json();
console.log(status);
const allDone = Object.values(status.conversion_status ?? {})
.every((v: any) => v.status === "completed");
if (allDone) break;
await new Promise((r) => setTimeout(r, 3000));
}
conversionId := "CONVERSION_ID"
delay := 3 * time.Second
for i := 0; i < 60; i++ { // timeout after ~5 minutes
req, _ := http.NewRequest("GET", "https://api.mathpix.com/v3/converter/"+conversionId, nil)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
resp, _ := http.DefaultClient.Do(req)
result, _ := io.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(result))
if bytes.Contains(result, []byte(`"completed"`)) {
break
}
time.Sleep(delay)
if delay < 15*time.Second {
delay = delay * 3 / 2 // backoff up to 15s
}
}
HttpClient client = HttpClient.newHttpClient();
String conversionId = "CONVERSION_ID";
while (true) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/converter/" + conversionId))
.header("app_id", "APP_ID").header("app_key", "APP_KEY").GET().build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
if (response.body().contains("\"completed\"")) break;
Thread.sleep(3000);
}
Example response while processing
{
"status": "completed",
"conversion_status": {
"docx": { "status": "processing" },
"tex.zip": { "status": "processing" }
}
}
Example response when all formats are ready
{
"status": "completed",
"conversion_status": {
"docx": { "status": "completed" },
"tex.zip": { "status": "completed" }
}
}
Download results
Once a format's status is "completed", download from GET v3/converter/{conversion_id}.{ext} by appending the format extension to the conversion ID:
- mpxpy
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
# Save to files
conversion.to_docx_file(path="result.docx")
conversion.to_tex_zip_file(path="result.tex.zip")
conversion.to_html_file(path="result.html")
# Or get content in memory
docx_bytes = conversion.to_docx_bytes() # bytes
md_text = conversion.to_md_text() # str
# Download DOCX
curl https://api.mathpix.com/v3/converter/CONVERSION_ID.docx \
-H 'app_id: APP_ID' \
-H 'app_key: APP_KEY' > result.docx
# Download LaTeX zip
curl https://api.mathpix.com/v3/converter/CONVERSION_ID.tex.zip \
-H 'app_id: APP_ID' \
-H 'app_key: APP_KEY' > result.tex.zip
# Download HTML
curl https://api.mathpix.com/v3/converter/CONVERSION_ID.html \
-H 'app_id: APP_ID' \
-H 'app_key: APP_KEY' > result.html
import requests
headers = {"app_id": "APP_ID", "app_key": "APP_KEY"}
conversion_id = "CONVERSION_ID"
# Download DOCX
r = requests.get(f"https://api.mathpix.com/v3/converter/{conversion_id}.docx", headers=headers)
with open("result.docx", "wb") as f:
f.write(r.content)
# Download LaTeX zip
r = requests.get(f"https://api.mathpix.com/v3/converter/{conversion_id}.tex.zip", headers=headers)
with open("result.tex.zip", "wb") as f:
f.write(r.content)
# Download HTML
r = requests.get(f"https://api.mathpix.com/v3/converter/{conversion_id}.html", headers=headers)
with open("result.html", "wb") as f:
f.write(r.content)
import fs from "fs";
const headers = { app_id: "APP_ID", app_key: "APP_KEY" };
const conversionId = "CONVERSION_ID";
// Download DOCX
const docx = await fetch(`https://api.mathpix.com/v3/converter/${conversionId}.docx`, { headers });
fs.writeFileSync("result.docx", Buffer.from(await docx.arrayBuffer()));
// Download LaTeX zip
const tex = await fetch(`https://api.mathpix.com/v3/converter/${conversionId}.tex.zip`, { headers });
fs.writeFileSync("result.tex.zip", Buffer.from(await tex.arrayBuffer()));
// Download HTML
const html = await fetch(`https://api.mathpix.com/v3/converter/${conversionId}.html`, { headers });
fs.writeFileSync("result.html", Buffer.from(await html.arrayBuffer()));
conversionId := "CONVERSION_ID"
for _, ext := range []string{"docx", "tex.zip", "html"} {
req, _ := http.NewRequest("GET", "https://api.mathpix.com/v3/converter/"+conversionId+"."+ext, nil)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
resp, _ := http.DefaultClient.Do(req)
data, _ := io.ReadAll(resp.Body)
resp.Body.Close()
os.WriteFile("result."+ext, data, 0644)
}
HttpClient client = HttpClient.newHttpClient();
String conversionId = "CONVERSION_ID";
for (String ext : List.of("docx", "tex.zip", "html")) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/converter/" + conversionId + "." + ext))
.header("app_id", "APP_ID").header("app_key", "APP_KEY").GET().build();
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("result." + ext), response.body());
}
Next steps
- v3/converter reference — Full request parameters, conversion options per format, and response schema
- Process a Document — documents can also request conversion formats automatically