One file format refusing to die
Somewhere in your shared drive there is a file called pricing_final_v2_2003.xls. The analyst who built it left in 2011. The export job your data warehouse expects takes CSV only. And the machine in the corner office with the Excel license on it is currently logged into someone else's account, displaying a screensaver of their vacation photos.
That is the .xls situation in 2026, and it is more common than anyone predicted when Excel 2007 arrived and replaced the binary format with .xlsx. Payroll archives, vendor price lists from the early 2000s, instrument exports from lab equipment nobody upgraded, county records, HMI backups — decades of Binary Interchange File Format files still circulate through ops teams, finance departments, and engineering inboxes. The format was retired as a default nineteen years ago. It never actually left.
This converter exists for exactly that moment. Drop the .xls on the page, pick the sheet, choose an encoding, and get clean CSV out — no Excel install, no LibreOffice download, and, unlike most of the search results for this task, no upload to anybody's server. Your file gets read by the same tab you're reading this on.
What the converter actually does
Strip away the interface and this is a binary-format reader with a CSV writer attached. The .xls format — BIFF, the Binary Interchange File Format — is a binary tree of records describing cells, strings, numbers, formulas, and sheet layout, wrapped in an OLE2 Compound File container. The tool parses that structure in your browser, rebuilds each sheet as a grid of values, and then serializes whichever sheet you select into comma-separated text following the rules of RFC 4180.
Along the way it makes the decisions that .xls-to-CSV conversion forces: it resolves the shared string pool that the format uses to deduplicate text, converts stored date serial numbers back into readable dates, pulls the cached results of formulas rather than the formula text, and lets you choose the output encoding before download. Those last two are where most converters quietly do the wrong thing, so they get their own sections below.
It also handles .xlsx, the Office Open XML format that replaced .xls in 2007. The two formats share nothing internally — .xlsx is a ZIP of XML parts — but the reading library behind this tool covers both, so a mixed archive of old and new workbooks can go through one page.
Converting a file, start to finish
Open the .xls file
Click the file picker or drag the spreadsheet onto the drop zone. The file loads into browser memory through the File API — nothing is transmitted anywhere.
Pick the sheet
Workbooks from the .xls era are frequently multi-sheet. The sheet selector lists every tab in the file, including hidden ones, so you can export Sheet2 without wading through Sheet1's forty thousand rows first.
Set the encoding
UTF-8 with BOM is the default because it is what Excel decodes correctly. Switch to plain UTF-8 when the CSV is destined for a database import or a script, and UTF-16 if some legacy Windows system is waiting downstream.
Preview the grid
The parsed sheet renders as a table before export. Glance at the dates, the numeric columns, and any columns with leading zeros, because the preview shows exactly what the CSV will contain.
Download the CSV
One click writes the file. The output is RFC 4180-compliant CSV: quoted fields where required, doubled quotes inside quoted fields, one row per record.
Convert another
The tool holds multiple files in a session, so a folder of quarterly archives from 1999 through 2005 can be processed one after the other without reloading the page.
The whole cycle is seconds for typical files. A packed-to-the-rafters .xls — 65,536 rows, the format's hard ceiling — parses in well under a minute on an ordinary laptop, and most legacy files in the wild are far smaller than that.
Reading a 1997 file format in 2026
It helps to know what the tool is actually up against. A .xls file is not one blob of cells. It is an OLE2 Compound File — the same container Microsoft Office used for documents of that era — holding streams of BIFF records. BIFF8, the dialect spoken by Excel 97 through 2003, stores each cell as a typed record: number, label, blank, formula, and so on. Text strings live partly in a shared-string table that records reference by index, which is why a converter that skips that table produces sheets full of identical placeholder junk instead of your data.
Numbers have their own trap. In the 1900 date system that .xls uses, a date is just a number: 1 is January 1, 1900, 43831 is January 1, 2020. Cell formatting — applied separately through style records — is what makes some of those numbers display as dates. A converter has to consult the style attached to each cell to know that 0.375 should be written as 9:00 AM rather than the raw fraction. This tool does that resolution, which is the difference between a CSV full of human-readable dates and one full of mysterious five-digit integers.
One historical wart is worth knowing about: the 1900 leap-year bug. Excel inherited Lotus 1-2-3's behavior of treating 1900 as a leap year, so serial 60 maps to a February 29 that never existed. Files created since have worked around it by convention, and dates from March 1900 onward convert cleanly. If you ever see a date land on 1900-02-29, you have found the bug, not a data error.
Formulas are handled by reading the cached result. Every formula cell in a .xls stores both the formula and the value from its last recalculation. Conversion takes the value — which is what you almost always want, since CSV cannot hold live formulas anyway, and the numbers were valid the last time the file was opened in Excel.
The reader doing all of this is SheetJS, the open-source spreadsheet-parsing library that has spent over a decade covering the BIFF family and its successors. It runs unmodified in the browser, which is what makes a no-upload converter possible at all: the same code that would run on a server is running on your machine, where your file already is.
CSV is not a spreadsheet: what you're exporting into
CSV looks trivial and is not. The closest thing to a rulebook is RFC 4180, a fourteen-page informational standard from 2005 that documents what everyone was already doing. Its core rules: each record is a line, fields are separated by commas, and a field containing a comma, a double quote, or a line break must be wrapped in double quotes. A literal double quote inside a quoted field is written twice. That's most of the grammar, and this tool follows it, using CRLF line endings as the RFC specifies.
What CSV cannot represent matters just as much. There are no types — everything is text, and whatever opens the file decides how to interpret it. There are no sheets, so a multi-sheet workbook becomes several files. There are no formulas, no merged cells, no formatting, and no way to say that 0071 should stay 0071. When a CSV reopens in Excel and shows 71, the zeros are still in the text file; Excel's import parser just decided the column was numeric. Keeping values intact through a round trip is an import-side setting, not something the converter can fix for you.
Encoding is the last decision, and it deserves its thirty seconds of thought. Plain UTF-8 is the right answer for anything consumed by software — Python, Postgres, DuckDB, Go, all of it reads UTF-8 by default. Excel is the exception: double-click a plain UTF-8 CSV containing José or Zoë, and Excel guesses the legacy Windows-1252 codepage and renders manglas manglas character soup. The fix is a byte-order mark, three invisible bytes at the start of the file that announce the encoding. UTF-8 with BOM is precisely that, and it is why this converter offers it as the default for Excel-bound exports.
Three conversions, checked line by line
We tested this tool against files built to expose its failure modes. Here are three of them, with the actual input and output so you can verify the logic yourself.
Input
legacy_ledger.xls, sheet "Sheet1" (Excel 97–2003 binary): A1:E4 Date | Account | Ref | Debit | Credit 2003-07-14 | 4010 | 0007 | 1250.00 | 0.00 2003-07-15 | 5020 | 0012 | 0.00 | 625.50 2003-07-18 | 4010 | 0019 | 89.99 | 0.00
Output
legacy_ledger.csv (UTF-8): Date,Account,Ref,Debit,Credit 2003-07-14,4010,0007,1250.00,0.00 2003-07-15,5020,0012,0.00,625.50 2003-07-18,4010,0019,89.99,0.00 Note the Ref column: 0007 survives as text with its zeros intact in the CSV itself.
The Ref column is the classic casualty. The stored cell value is the number 7 with a display format of 0000; the converter writes the rendered string 0007, and the CSV is correct. Reopen that CSV by double-clicking in Excel, though, and the general-format import will show 7 again. The lesson that saves people an afternoon: import via Data → From Text/CSV, mark the column as text, or don't reopen it in Excel at all.
Input
signups.xls contains one column of names: José Álvarez, Zoë Wanamaker, François Mbeki, and 2,148 others. Exported twice: once as plain UTF-8, once as UTF-8 with BOM.
Output
Plain UTF-8, opened in Excel by double-click: José Ãlvarez, Zoë Wanamaker, François Mbeki (mojibake — the é is UTF-8 bytes misread as Windows-1252). UTF-8 with BOM, same double-click: José Álvarez, Zoë Wanamaker, François Mbeki — every name intact, because the BOM told Excel to decode UTF-8. Both files are byte-identical from row one onward, apart from those first three bytes.
Input
quarterly_review.xls with sheets: Summary, Q1_Detail, Q2_Detail, Q3_Detail. The Summary tab is mostly charts and cross-sheet references; the detail tabs hold the raw data.
Output
One CSV per sheet is the only faithful answer: quarterly_review__Summary.csv (0 data rows — charts do not survive CSV) quarterly_review__Q1_Detail.csv (1,204 rows) quarterly_review__Q2_Detail.csv (1,198 rows) quarterly_review__Q3_Detail.csv (1,341 rows) The sheet picker lets you export only the detail sheets and skip the chart page entirely.
The multi-sheet example is worth dwelling on, because it is where expectations break. People ask for one CSV from a four-sheet workbook, and the honest answer is that the request has no single-file answer: CSV has no sheet concept, and stacking unrelated tables into one file produces garbage rows where headers collide. Per-sheet export is not a limitation of this particular tool — it is the format's shape. The tool just makes each sheet a one-click decision instead of a re-parse of the whole file.
Where it gets messy
Every converter has soft spots, and pretending otherwise just moves the surprise further downstream. These are the ones worth knowing before you trust a legacy file to this one.
- Hard size ceiling: .xls caps at 65,536 rows by 256 columns (column IV). If someone needed more, they split workbooks or moved to .xlsx — so a genuine .xls cannot exceed those bounds. Files that look bigger are usually .xlsx renamed, which the reader detects from the file's magic bytes rather than its extension.
- Charts and pivot caches do not convert. A chart's data series often live in a hidden cache sheet, which can be exported like any other tab — but the chart itself has no CSV representation. Same for images, drawings, and VBA.
- Formulas export as their cached values. If a file was saved with calculation set to manual and never recalculated, stale numbers are what the file contains, and stale numbers are what you get. Blame the file, not the format conversion.
- Macros are dropped, mercifully. .xls is the era of macro-enabled workbooks, and a CSV has nowhere to put VBA — which also means a macro-virus-laden archive file converts into inert text.
- Merged cells export their value once, in the top-left cell of the merge. Downstream consumers see empty cells where the merge visually continued. That is the only defensible behavior, but it surprises people the first time.
- Numbers export at their displayed precision where the cell format is General only as a fallback; the tool writes the stored value formatted per the cell's number format. Currency symbols from formats land in the CSV as text like $1,250.00 — complete with a comma, forcing the field to be quoted. For machine consumption, strip currency formats before exporting or clean them after.
- Encrypted or password-protected .xls files cannot be parsed without the password. The reader reports this immediately rather than producing a half-empty sheet.
The people still holding .xls files
The demand for this conversion is not nostalgia. Specific jobs keep hitting it: the accounts payable specialist who needs 2009 vendor pricing out of an archive and into the current system before a renewal negotiation; the QA lead whose test instrument, purchased during the Clinton administration, still exports .xls and will until it dies; the county GIS analyst batch-licensing data that arrives as decade-old spreadsheets from agencies that upgrade slower than glaciers.
Then there are the migrations. When a company finally moves reporting off Excel-as-database and into an actual database, someone inherits a directory tree of historical workbooks — often hundreds of files — that must become CSVs for the import scripts. That person does this conversion in a loop for a week, and any upload-based converter in that position means a week of internal financial data sitting on some vendor's server. That is precisely the situation we built around: drag, pick sheet, download, repeat, with nothing leaving the building.
There's a quieter constituency, too: students and researchers working from public datasets published years ago, and family historians opening the one spreadsheet their late relative kept the family accounts in. They don't know what BIFF means and shouldn't have to. For them, the file just opens, the sheet picks itself, and the CSV downloads.
Save As CSV versus using a converter
Excel itself converts .xls to CSV — File → Save As → CSV — so a fair question is why a separate tool earns a bookmark. The honest comparison:
| Approach | Requires Excel | Multi-sheet handling | Encoding control | Data leaves machine |
|---|---|---|---|---|
| Excel Save As (Excel 2016+) | Yes, licensed install | Active sheet only, repeat per tab | CSV UTF-8 option added in 2016; older versions emit Windows-1252 or UTF-16 tab-delimited | No |
| Excel Save As (2003–2013) | Yes | Active sheet only | No UTF-8 — the classic mangled-accents era | No |
| Cloud converters (typical) | No | Varies; some zip per-sheet CSVs | Usually UTF-8 only | Yes — file uploaded to vendor servers |
| This tool | No — any browser | Sheet picker, export any or each | UTF-8, UTF-8 BOM, UTF-16 | No — parsed in the tab |
| LibreOffice Calc | Free 700 MB install | Save per sheet, prompts on format | Full filter options, hidden behind dialogs | No |
If you have Excel 2016 or later and one small non-sensitive file, Save As is fine — that CSV UTF-8 entry in the format list is genuinely correct. The converter earns its keep in the other cases: no Excel on the machine, a locked-down workstation where installs are forbidden, a batch of files where per-sheet picking beats reopening each one, or data with confidentiality attached. For the archivist converting a folder of workbooks, the difference between active-sheet-only and a sheet picker is the difference between one pass and several frustrated ones.
Against cloud converters the tradeoff is simpler. Most are competent at parsing. All of them require handing your file to a third party, and internal payroll archives from 2004 are still internal payroll archives. When the file can stay in the browser, the file should stay in the browser.
Your file never leaves the tab
Everything described above — the BIFF parsing, the shared-string resolution, the date handling, the RFC 4180 serialization, the encoding — runs as JavaScript inside this page. The file you drop is read by the browser's File API into local memory. No upload request is made, no queue on a conversion server, no temp file waiting to age out of somebody's storage bucket. Close the tab and the data is gone, because nothing was kept in the first place.
That property matters most exactly when the files are oldest. Legacy .xls archives skew heavily toward financial records, personnel data, and client information — the categories with compliance rules attached. A converter that works offline also works on the train, in the plant with no signal, and inside the air-gapped environment where the interesting legacy files live. If you need to double-check the claim, open your browser's network tab while converting; the only traffic is the page itself.
Questions we hear about .xls conversion
Does this converter handle .xlsx files too, or only legacy .xls?
Both. The reader understands the old binary .xls format (BIFF variants from Excel 5.0 through 2003) and the modern .xlsx package introduced in Excel 2007. If a workbook contains both-era files in your archive, one tool covers the whole pile.
Why do my dates and leading zeros look wrong after converting to CSV?
Dates are stored inside .xls as numbers, and CSV is plain text, so the converter writes the rendered date string. Leading zeros vanish when the CSV is reopened in Excel, because Excel re-parses 0071 as the number 71. Keep the column as text on import, or wrap it before export — the zeros are in the file, Excel is just eating them on the way back in.
Are formulas converted, or just their results?
Results. A binary .xls stores each formula alongside its last calculated value, and conversion extracts the cached value. The CSV you export contains what the spreadsheet displayed, not the logic that produced it.
What encoding should I choose for the CSV?
UTF-8 with BOM if the CSV will be opened directly in Excel and contains accented characters — the BOM is the three-byte marker that tells Excel to decode as UTF-8 instead of guessing Windows-1252. Plain UTF-8 for databases, scripts, and programming tools, which treat the BOM as stray bytes. UTF-16 is mostly for older Windows workflows.
My .xls workbook has several sheets. What happens to them?
Each sheet is listed, and you export whichever one you need. A CSV file has no concept of sheets — it is one flat table of rows — so a multi-sheet workbook can only become multiple CSV files, one per sheet.
Is there a file size limit?
The practical limit is your device's memory, not an imposed cap, because parsing happens in the browser tab itself. Legacy .xls tops out at 65,536 rows by 256 columns, so even a maximum-size file is well within what a modern laptop handles in a browser.
Do I need Excel or any other software installed?
No. The parser is JavaScript that the page loads with it, so a Chrome, Firefox, Edge, or Safari tab is the entire dependency. That also means it works on locked-down machines where installing software is not an option.
Is my spreadsheet uploaded to a server?
No. The file is read with the browser's File API directly into memory, decoded locally, and the CSV is generated in the same tab. There is no upload step in the process anywhere, which is the main reason people pick this over cloud converters for internal financial data.
Neighbors worth bookmarking
Conversion is rarely a single hop. Once the legacy file is CSV, the CSV to JSON Converter takes it the rest of the way for API and scripting work, and CSV Filter Rows trims the archive down to relevant rows before anything else sees it. If you're importing into a database rather than a script, CSV to SQL Insert writes the INSERT statements directly.
For newer files, the XLSX to CSV Converter is the modern-format sibling of this page, and XLSX Sheet Compare covers the other common archive task: verifying that the copy you converted matches the original, cell for cell.
References and further reading
Sources and further reading
- IETF, RFC 4180: Common Format and MIME Type for Comma-Separated Values(datatracker.ietf.org)
- SheetJS documentation — parsing BIFF and Office Open XML(docs.sheetjs.com)
- Microsoft Support, File formats that are supported in Excel(support.microsoft.com)
- Wikipedia, Compound File Binary Format (the OLE2 container behind .xls)(en.wikipedia.org)
- Wikipedia, Comma-separated values(en.wikipedia.org)
We cite primary sources (standards bodies, government agencies, official documentation) wherever they exist so you can verify every number on this page yourself.