Excel to JSON Converter — XLSX/XLS Spreadsheet, All Sheets API avatar

Excel to JSON Converter — XLSX/XLS Spreadsheet, All Sheets API

Pricing

from $24.00 / 1,000 file conversions

Go to Apify Store
Excel to JSON Converter — XLSX/XLS Spreadsheet, All Sheets API

Excel to JSON Converter — XLSX/XLS Spreadsheet, All Sheets API

Convert XLSX or XLS spreadsheet URLs to JSON via API. Extract every sheet as row objects with detected headers, or select one sheet. Process up to 25 workbooks per run. Free-plan rate: $0.03 per workbook, all sheets included; Store discounts available.

Pricing

from $24.00 / 1,000 file conversions

Rating

0.0

(0)

Developer

Broke to Built

Broke to Built

Maintained by Community

Actor stats

0

Bookmarked

24

Total users

19

Monthly active users

4 days ago

Last modified

Share

Excel to JSON Converter — XLSX & XLS to clean JSON, by URL or in bulk

Point it at an .xlsx or .xls URL, get back every sheet as an array of row objects with the header row detected for you. One workbook or up to 25 in a single run. Nothing to install, and it is built to be called by code and by AI agents, not just clicked.

$0.03 per file converted. No subscription, no seat fee, no minimum.

What problem this solves

Excel is where the data lives and JSON is where the code needs it. Getting from one to the other usually means installing a parser, learning its quirks about merged cells and header rows, and writing throwaway glue — or pasting a spreadsheet that may contain client data into a random free website.

This does the conversion as a hosted step you can call from a script, a workflow, or an agent. Nothing to install, and the file is fetched from the URL you give it.

Who uses it

  • Data and ops engineers wiring a vendor's weekly .xlsx export into a pipeline.
  • Analysts who need a sheet as JSON for a notebook, a chart, or an API payload.
  • AI agents handed a spreadsheet link that need structured rows to reason over.
  • No-code / automation builders (Make, n8n, Zapier, and similar) that can call a URL but cannot parse a binary workbook.
  • Anyone doing a bulk migration — hand it 25 workbook URLs, get 25 dataset items.

Common requests this handles

Phrased the way people actually ask for it, so you can tell at a glance whether this is the right tool before you spend anything:

  • "Read an xlsx spreadsheet into structured data." Every sheet comes back as an array of row objects keyed by the detected header row — structured JSON, not a flat cell dump.
  • "Turn a customer xlsx into JSON records." One record per sheet, one object per row. Multi-sheet workbooks stay separated rather than being merged into one table.
  • "Extract data from an Excel workbook by URL." The file is fetched from the URL you pass; there is no upload step and nothing is stored after the run.
  • "XLSX to JSON API without a spreadsheet vendor key." No separate spreadsheet-service account or parser installation is needed. HTTP clients authenticate with an Apify API token; the Console uses your signed-in Apify account.
  • "Convert xls, not just xlsx." Legacy .xls is handled by the same input field.
  • "Do it for 25 files at once." Pass a list of URLs; each becomes its own dataset item, and a file that fails to parse is reported and not charged.

Quick start

{
"url": "https://go.microsoft.com/fwlink/?LinkID=521962"
}

That is the whole minimum input (the URL above is Microsoft's public Financial Sample workbook — a real 700-row sheet you can test with right now). Everything else is optional.

All input options

FieldTypeRequiredWhat it does
urlstringyesDirect URL to the .xlsx / .xls workbook
urlsstring[]noExtra workbook URLs — up to 25 total per run
sheetstring | numbernoSheet name, or 0-based index. Omit to convert every sheet
maxRowsnumbernoCap data rows per sheet (default 5000, up to 100,000)
maxFileSizeMbnumbernoSkip files larger than this (default 50, up to 200). Oversized files are recorded as failed and never charged

What you get back

One dataset item per input URL:

FieldMeaning
urlThe URL you supplied
finalUrlWhere the fetch actually landed, after redirects
statusHTTP status of the download
sheetNamesEvery sheet found in the workbook, in workbook order
sheets[name].columnsThe detected header row, blanks named column_1, column_2, …
sheets[name].rowsData rows as objects keyed by those headers
sheets[name].rowCountRows returned for that sheet, after maxRows
errorPresent instead of the above when that one URL failed. Never charged

Examples

Both outputs below are copied from real runs of this actor, trimmed to the first rows.

1. A multi-sheet workbook, all sheets at once

Input:

{ "url": "https://graveyard.broke2builtai.com/assets/sample.xlsx" }

Output item:

{
"url": "https://graveyard.broke2builtai.com/assets/sample.xlsx",
"finalUrl": "https://graveyard.broke2builtai.com/assets/sample.xlsx",
"status": 200,
"sheetNames": ["Products", "Orders"],
"sheets": {
"Products": {
"rowCount": 3,
"columns": ["Product", "Price", "Stock"],
"rows": [
{ "Product": "Lantern", "Price": "12.5", "Stock": "42" },
{ "Product": "Headstone", "Price": "99", "Stock": "12" },
{ "Product": "Candle", "Price": "1.25", "Stock": "500" }
]
},
"Orders": {
"rowCount": 2,
"columns": ["OrderId", "Product", "Qty"],
"rows": [{ "OrderId": "1001", "Product": "Lantern", "Qty": "3" }]
}
}
}

2. A 700-row business sheet with currency and date formatting

Input:

{ "url": "https://go.microsoft.com/fwlink/?LinkID=521962", "maxRows": 2 }

Output item (trimmed):

{
"url": "https://go.microsoft.com/fwlink/?LinkID=521962",
"finalUrl": "https://download.microsoft.com/download/1/4/E/.../Financial%20Sample.xlsx",
"status": 200,
"sheetNames": ["Sheet1"],
"sheets": {
"Sheet1": {
"rowCount": 2,
"columns": ["Segment", "Country", "Product", "Units Sold", "Sale Price", "Gross Sales", "Profit", "Date", "Year"],
"rows": [
{
"Segment": "Government", "Country": "Canada", "Product": " Carretera ",
"Units Sold": "1618.5", "Sale Price": " $20.00 ", "Gross Sales": " $32,370.00 ",
"Profit": " $16,185.00 ", "Date": "1/1/14", "Year": "2014"
}
]
}
}
}

Note what that second example shows honestly: values arrive as the sheet displays them" $20.00 " rather than 20, "1/1/14" rather than an Excel serial number, including the padding the author typed. That is deliberate: currency, percentages and dates survive intact instead of turning into raw serials. If you want numbers as numbers, strip and cast on your side.

3. A bad URL never kills the batch

{ "url": "https://example.com/not-a-workbook.xlsx" }
{ "url": "https://example.com/not-a-workbook.xlsx", "error": "HTTP 404 fetching file" }

Errors are specific: a URL that serves an HTML page instead of a workbook (the classic wrong-share-link mistake) says exactly that, not a cryptic parse failure. Failed inputs are recorded and never charged.

Call it from code

curl — synchronous run, JSON straight back:

curl -X POST "https://api.apify.com/v2/acts/eliai~excel-to-json/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/report.xlsx"}'

Python (pip install apify-client):

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("eliai/excel-to-json").call(
run_input={"url": "https://example.com/report.xlsx"}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
for sheet, data in item["sheets"].items():
print(sheet, data["rows"][:3])

Node.js (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('eliai/excel-to-json').call({
url: 'https://example.com/report.xlsx',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].sheets);

Converting a Google Sheet

A Google Sheets share page is not a file URL — but every Google Sheet has an export URL that serves a real .xlsx:

https://docs.google.com/spreadsheets/d/FILE_ID/export?format=xlsx

Set the sheet's sharing to "anyone with the link", swap in your FILE_ID, and pass that as url. The whole spreadsheet converts like any other workbook.

Use it as an AI agent tool

This Actor is callable over Apify MCP, so an agent can convert a spreadsheet mid-conversation without you writing an integration. The shape an agent needs:

  • Tool: this Actor
  • Input: { "url": "<xlsx url>" }
  • Returns: parsed sheets as JSON rows

If your agent can be handed a link to a workbook, it can now read the contents.

Automate it

Everything the Apify platform offers works here with zero extra code: schedule a recurring conversion of a URL that updates (a vendor's daily export), fire a webhook when a run finishes, or drop it into Make, Zapier, or n8n with the standard Apify app — pick this Actor, pass the JSON input above, and use the dataset items downstream.

It tells you whether the file actually changed

Point it at a URL that gets re-published — a vendor export, a shared sheet, a daily report — and every run reports whether the contents moved since the last one:

fieldmeaning
isBaselineRuntrue on the first run for a URL; the baseline was just recorded
changedtrue when the sheet contents differ from the previous run
changeSummaryone line you can put straight into an alert
trackingPersistsfalse if your plan could not open a named store, so every run reads as a first run

The comparison is on the parsed contents — sheet names and rows — not on the URL, the redirect chain or the HTTP status, so a host that re-issues headers or bounces through a redirect on every request does not report a false change.

Practical use: schedule it hourly or daily, add a webhook, and only do downstream work when changed is true. You stop re-processing identical files, and you find out about a silent upstream edit the day it happens rather than the week you notice.

Pricing

Pay per event, one event: file-converted.

EventWhat one event coversPrice
file-convertedOne workbook downloaded and converted — every sheet in it included$0.03

A 25-workbook batch costs $0.75. A 12-sheet workbook still costs $0.03, because the charge is per file, not per sheet. There is no start fee, no monthly fee, and a run that converts nothing costs nothing. Files that fail — dead link, HTML instead of a workbook, over the size cap — are recorded with an error and never billed.

Honest comparison: if you are already writing Python, pandas.read_excel(url) does this for free. What you are paying $0.03 for is the hosted version — no runtime to install, no dependency to pin, batching, size caps, per-file error isolation, and a dataset a no-code tool or an agent can consume. If you have a Python environment and one file, use pandas.

When NOT to use this

  • You already have Python or Node running. pandas.read_excel / SheetJS is free and local. Use this when you need a hosted step, not a library.
  • The file is behind a login or on a private network. This fetches only public URLs you supply — no credentials, no cookies, no crawling.
  • The workbook is password-protected. Not supported; it will fail that file.
  • You need formulas, charts, macros, styling, or cell colours. You get computed values as text, not the workbook's logic or its formatting metadata.
  • You need the file uploaded from your machine. The input is a URL. Host it first, or use the Google Sheets export recipe above.
  • You need CSV, not Excel. Use our CSV to JSON converter instead — it is cheaper per file and handles delimiters and type inference.

Honest limits

  • The workbook must be reachable at a direct URL. A Google Sheets share page is not a file URL — use the export link (recipe above), or host the file somewhere fetchable.
  • Password-protected workbooks are not supported.
  • Formulas come back as their computed values, not the formula text.
  • Values are returned as displayed strings, not typed numbers (see example 2).
  • Merged cells follow the underlying sheet layout, so a heavily merged "report" sheet converts less cleanly than a flat data table.
  • Large workbooks are bounded by maxRows per sheet — raise it deliberately.
  • Files over maxFileSizeMb (default 50 MB) are skipped, recorded, and never charged.
  • Hard cap of 25 workbooks per run; split larger batches across runs.

FAQ

How do I convert an Excel file to JSON without installing anything?

Give this Actor the file's URL. It fetches the workbook, parses every sheet, and returns JSON rows. No local install, no library to learn.

Can it convert every sheet in the workbook at once?

Yes — that is the default. Omit sheet and you get all of them, keyed by sheet name. Pass sheet to narrow to one, by name or 0-based index.

Does it handle .xls as well as .xlsx?

Yes, both legacy .xls and modern .xlsx.

Can I convert a Google Sheet to JSON?

Yes — use the export URL (.../export?format=xlsx) with link sharing on. See "Converting a Google Sheet" above for the exact recipe.

How does it know which row is the header?

The first row becomes the object keys in rows, and the detected headers also come back as columns so you can check what it decided. Blank header cells get stable names (column_1, column_2, …) so no data is lost.

Why are my numbers strings, and how are dates handled?

Cell values come back the way the sheet displays them, so currency, percentages and dates keep their formatting instead of arriving as raw serial numbers. The trade is that 20 formatted as currency arrives as " $20.00 ". Cast on your side if you need numeric types.

Can I convert multiple Excel files in one run?

Yes — up to 25 per run via urls. Each produces its own dataset item, and a failure on one does not stop the rest.

Am I charged per sheet or per file?

Per file. A workbook with twelve sheets is one file-converted event, $0.03.

What happens if a file is missing or is not a real workbook?

That input returns { url, error } with a specific message — including the common case where the URL serves an HTML page instead of the file. The run continues and the other files still convert. Failed inputs are never charged.

What happens when my run spending limit is reached?

The Actor checks the remaining budget before each workbook. If it cannot cover one more conversion, the batch stops with a BUDGET_EXHAUSTED record and the number of remaining files. Already converted files remain available. Increase your spending limit and submit only the remaining files if you want to continue.

Where does my spreadsheet data go?

The Actor fetches the file, parses it, and writes the result to your run's dataset on your own Apify account. Delete the run and the output goes with it.

Can an AI agent call this?

Yes — it is exposed through Apify MCP as an agent tool. See "Use it as an AI agent tool".

Who made this

Broke to Built — a company of machines, building things it gives away. This is one of them; the rest are free too.

For AI agents

This Actor is built to be called by software, not just by people.

  • Mount it directly as an MCP tool — no Store search, no ranking, just this one tool: https://mcp.apify.com/?actors=eliai/excel-to-json
  • Or call it over HTTP and get the results in the same request: POST https://api.apify.com/v2/acts/eliai~excel-to-json/run-sync-get-dataset-items
  • Pay with x402, without an Apify account. This Actor is whitelisted for agentic payments, so an agent holding USDC on Base can buy a prepaid token and spend it here. The minimum purchase is $1, the token balance is an absolute spending cap, and it expires 14 days after purchase.
  • Costs are predictable before you call. Pricing is pay-per-event (see Pricing above), so an agent can budget a run in advance instead of discovering the bill afterwards.
  • Send only the field you mean. If you pass the bulk field, it is used on its own; the single-value field is a fallback, never merged into your request. You are charged for the items you sent and nothing else.

Changelog

2026-09-05 (listing clarity). Clarified that HTTP clients use an Apify token and replaced the old API example URL with the workbook used by the current input form. Conversion and billing are unchanged.

  • 2026-09-05: Batch conversion now stops before processing a workbook that exceeds your remaining run budget. Delivery and billing failures stop the batch for review. Prices and the per-workbook charge unit are unchanged.

  • 2026-08-28: Every run now reports whether the file's contents CHANGED since the last run for that URL (changed, isBaselineRun, changeSummary, trackingPersists). The comparison is on parsed sheet names and rows, so a redirect or a re-issued header does not report a false change. Nothing was removed and prices are unchanged — schedule the Actor and act only when changed is true.