Skip to content
pdfconversionapi

XLS to MD API

Upload an .xls workbook to POST /v2/convert/xls/to/md and receive a Markdown file with one table per sheet, each under a ## heading. The sample's Fuel and Vans sheets fill 1,376 bytes.

Endpoint
POST /v2/convert/xls/to/md
Accepts
xls
Sample timing
under 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/xls/to/md \
  -H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
  -F File=@van-fuel-log.xls \
  -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
fi
200 OKunder 1 ms median1 file, 1.3 KB
{
  "ConversionCost": 1,
  "ConversionTime": 0,
  "Files": [
    {
      "FileName": "van-fuel-log.md",
      "FileExt": "md",
      "FileSize": 1376,
      "FileData": "IyMgRnVlbAoKfCBEYXRlIHwg…"
    }
  ]
}

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.

van-fuel-log.md, 26 lines

## Fuel| Date | Van | Odometer | Gallons | Price per gallon | Cost | Miles per gallon | Notes || --- | --- | --- | --- | --- | --- | --- | --- || 2026-06-01 | Van 1 | 48210 | 14.2 | 3.689 | 52.3838 | 16.619718309859156 |  || 2026-06-02 | Van 2 | 61377 | 16.8 | 3.689 | 61.9752 | 15.595238095238095 |  || 2026-06-04 | Van 3 | 30554 | 12.5 | 3.719 | 46.4875 | 18.24 |  || 2026-06-08 | Van 1 | 48463 | 15.1 | 3.749 | 56.6099 | 16.75496688741722 |  || 2026-06-09 | Van 2 | 61598 | 15.9 | 3.749 | 59.6091 | 13.89937106918239 | Receipt missing;<br>entered from bank statement || 2026-06-11 | Van 3 | 30791 | 13 | 3.759 | 48.867 | 18.23076923076923 |  || 2026-06-15 | Van 1 | 48701 | 14.6 | 3.729 | 54.4434 | 16.3013698630137 |  || 2026-06-16 | Van 2 | 61859 | 18.4 | 3.729 | 68.6136 | 14.184782608695654 | Idled during ice delivery || 2026-06-18 | Van 3 | 31043 | 12.9 | 3.699 | 47.7171 | 19.53488372093023 |  || 2026-06-22 | Van 1 | 48950 | 15.3 | 3.699 | 56.5947 | 16.274509803921568 |  || Total |  |  | 148.7 |  | 553.3013 |  |  |## Vans| Sunrise Rye Bakery: delivery vans |  |  |  || --- | --- | --- | --- || Fictional business. Sample file for pdfconversionapi.com, CC0 1.0. |  |  |  ||  |  |  |  || Van | Model year | Tank (gal) | Route || Van 1 | 2019 | 24 | North loop || Van 2 | 2021 | 26 | Downtown cafes || Van 3 | 2017 | 22 | Farmers markets |
Input
van-fuel-log.xls (11 KB)
Output
van-fuel-log.md (1.3 KB)
Source
A fictional bakery's van fuel log in Excel 97-2003 format (two sheets, formulas, a cell note and a merged title) that we wrote for this site (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.

ParameterWhat it does
SheetHeadingsboolean, default truePut the sheet name as a ## heading above each table; false leaves the tables bare. With WorksheetName=Vans as well, the output is a single 324-byte table.
FirstRowIsHeaderboolean, default trueTake each sheet's first row as the table header. false heads the table with column letters A, B, C.
WorksheetNamestringConvert one sheet by name instead of all of them; case is ignored.
WorksheetIndexintegerConvert the sheet at this position, from 1.Values: 1 to the number of sheets
ActiveWorksheetOnlyboolean, default falseConvert only the sheet selected when the file was saved. For the sample that is Fuel, and the output shrinks to 1,043 bytes.

Not supported yet

Setting one of these to anything but its default returns 400.

OptionWhat to do instead
CellValuesraw and other values return 400; formatted is accepted, though cells hold stored values, not the displayed text.
IncludeHiddenRowstrue returns 400 "IncludeHiddenRows is not supported yet for XLS → MD". Hidden rows are written in any case.
IncludeHiddenColumnstrue returns 400; hidden columns are written in any case.
ImagesOnly embed is accepted; other values return 400 "Images is not supported yet for XLS → MD".

What carries over, and what doesn't

Kept

  • Both sheets in tab order under ## Fuel and ## Vans
  • Line breaks inside a cell as <br>: the note reads "Receipt missing;<br>entered from bank statement"
  • Dates in ISO form (2026-06-01) and whole numbers without a decimal point (48210)
  • Empty cells as empty table cells, so the Total row lines up with the header

Lost or not yet supported

  • Number formats: prices and costs lose their dollar signs and are not rounded, so the miles-per-gallon column shows values like 16.619718309859156.
  • Merged cells: the Vans title becomes a header row followed by empty cells, and the table's real header ends up as a data row.
  • The cell note on A6, the drop-down list and the conditional highlight.

Limits

  • Excel's binary .xls format only. HTML saved under a .xls name returns 422 "the input file could not be read: Cannot detect file format".
  • A password-protected .xls returns 400 "password-protected XLS files can't be converted to MD yet" even with the right Password, and 422 without one. Password sent with an unprotected file is accepted and changes nothing. Re-save a protected file with /v2/convert/xls/to/xlsx and Password first, then convert the XLSX.
  • Requests up to 10 MB on the Free plan or 100 MB on paid plans; a conversion has 120 seconds before a 504.

Where teams use it

Reading old workbooks in a pull request or a wiki

Commit the Markdown next to the .xls so reviewers can see what a legacy file contains without opening Excel.

Feeding legacy spreadsheets to a language model

Every sheet arrives as a labeled table of plain values in a small text file, 1,376 bytes for the sample, instead of a binary workbook.

Questions

Can I get just one sheet?

Yes: WorksheetName, WorksheetIndex or ActiveWorksheetOnly=true each limit the output to a single table. Without them, every sheet is converted, hidden sheets included.

Why are the numbers longer than in Excel?

Markdown cells hold the value stored in the file, and the sheet's number format only shows it rounded. The fuel log's 16.6 is stored as 16.619718309859156, and that full value is what you get.

How are merged title cells handled?

The text stays in the first cell of the merged range and the other cells are empty. A title above a table therefore becomes the table header, as on the sample's Vans sheet.

Convert your first XLS file in a minute.