OpenSpout: streaming spreadsheets through PHP in three megabytes
Read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way
At a glance
- What is it?
- OpenSpout is a community driven fork of Box's Spout library for reading and writing CSV, XLSX and ODS files with a memory footprint the README puts at under three megabytes, whatever the file size. It carries a split licence, inherited Apache code from Box and MIT code since, and it now ships on a 5.x branch while the repository's homepage link still points at the 4.x docs.
- Who is it for?
- OpenSpout fits a PHP service that exports a report to a spreadsheet with a million rows and cannot hold it in memory, and a team that wants a well maintained successor to the original Spout library without changing the shape of the API. It does not fit a project that needs to read a spreadsheet with heavy formatting intact, since this is a data library rather than a document library, and it does not fit a team that cannot decide between the 4.x and 5.x lines.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The fork, and the two step upgrade from Spout
OpenSpout is a community driven fork of box/spout, a PHP library to read and write spreadsheet files in CSV, XLSX and ODS, in a fast and scalable way. The claim that distinguishes it from other readers and writers is that it is capable of processing very large files while keeping the memory usage really low, less than 3MB.
That number is the design, not a benchmark result. A library that keeps its own memory under three megabytes while the file is arbitrarily large has to be streaming rather than loading, and everything else in the project follows from that choice.
The migration from the original is deliberately small, and the README gives it in two steps. Replace box/spout with openspout/openspout in your composer.json, and replace the Box\Spout namespace with OpenSpout in your code. There is no third step, and that is a real statement about the fork's intent: to be a drop-in for the library people were already using.
The project is written in PHP, the licence situation is described in a dedicated section, the default branch is 5.x, and the last push to the repository was on 2026-10-13, with v5.12.2 released the same day, after v5.12.1 on 2026-10-12 and v5.12.0 on 2026-09-24.
A licence that changes at a specific commit
The copyright section is the most carefully worded part of the README, and it is worth reading in full rather than paraphrasing.
The code until and directly descending from a specific commit, cc42c1d, is copyright of Box, Inc. and licensed under the Apache License, Version 2.0. The code created, edited and released after that commit is copyright of the openspout GitHub organisation and licensed under the MIT License.
So this is not a project that relicensed Box's code, it is a project that continued from a point and applied a different licence to everything since. The repository reflects that with two licence files at the root, the main LICENSE and LICENSE-for-cc42c1d.
For a user, the practical consequence is small and mostly about redistribution. If you vendor the library into a product, the portion inherited from Box carries the Apache obligations and the newer portion carries MIT, and the boundary is a specific commit rather than a file list, so the check has to be done against history.
The same care shows up in the upgrade path. Version 4 introduced new functionality but also some breaking changes, and the README points to an Upgrade guide document in the repository rather than trying to summarise the changes in a list, which is the right call for a library that has been through a major version and a fork at the same time.
The documentation still points at the previous major line
There is a small inconsistency in the repository that a reader will trip over, and it is worth flagging because it affects how you evaluate the project.
The default branch is 5.x, and the releases are on the 5.12.x line. The homepage link in the repository metadata points at the documentation directory of the 4.x branch, and the README's own link to the documentation points at docs/ in the current tree.
That means the published documentation site and the current code are not necessarily the same documentation, which is exactly the situation where a reader ends up implementing an API that the installed version does not have, or the other way round.
The resolution is simple in practice. The docs/ directory in the branch you are on is the documentation for that branch, and the 4.x tree is what the homepage link shows. If you are on 5.x, read the 5.x docs and use UPGRADE.md for the differences from 4.x.
The formats themselves have not changed shape. The library reads and writes CSV, XLSX and ODS, and the description makes no claim about preserving formatting, charts or macros, because it is a data library rather than a document library. That distinction matters when you evaluate it, since a user coming from a document automation tool will find a very different set of capabilities here.
Mutation testing in the build, and a Docker-first workflow
The repository is one of the better equipped PHP libraries for CI, and the tooling tells you what the maintainers care about.
The Makefile runs everything inside a container, with docker compose run --rm as the base command, so the local toolchain and the CI toolchain are the same image. The Makefile has a .env target that derives the user and group ids from the host, and the Dockerfile is based on php:8.4.19-cli, creating a user with the matching ids, and installing the composer, pcov and zip extensions with the standard PHP extension installer, since git is needed for the mutation testing tool.
The default target is csfix, static-analysis and code-coverage in that order, and the code-coverage target runs infection, the mutation testing framework, with --git-diff-lines and a base branch, and --threads set to the number of processors. Infection is the interesting part: it mutates your code and checks whether the test suite notices, and limiting it to the lines you changed means a pull request gets checked for the mutants it introduces rather than for the entire history.
The supporting configuration is extensive. There is php-cs-fixer for style, PHPStan with a baseline file, PHPUnit for the tests, an infection configuration, a phpbench configuration with a benchmarks/ directory, a require-checker configuration that verifies the declared dependencies match what the code actually uses, mkdocs for the documentation build, and a Renovate configuration for dependency updates.
The baseline file for PHPStan is the one artefact of a mature codebase to be slightly careful with, since a baseline is a list of known issues that are not allowed to grow, but the existence of one at all usually means the count is small and the project tracks it.
A release cadence that suggests an actively maintained fork
The version history is the last thing to check, and it is reassuring.
v5.12.0 was released on 2026-09-24, v5.12.1 on 2026-10-12 and v5.12.2 on 2026-10-13, and the repository was last pushed to on 2026-10-13, the same day as the last tag. Two patch releases in three weeks, with the second one following the first by a day, is the pattern of a library that is being used and fixed rather than merely kept alive.
The continuity with the original is worth noting too, because it is the reason a fork can work at all here. The upgrade path from box/spout v3 is two find and replace operations, the API shape carried over, and the successor is developed by a community rather than by a company that stopped caring. A library that other people's spreadsheets depend on is exactly the case where the fork pattern beats the volunteer pattern, as long as someone is maintaining it, and the release cadence says that somebody is.
The combination to keep in mind when you evaluate it is therefore: a mature API, a permissive licence for the new code, an inherited Apache obligation for the old, a streaming design that is genuinely different from the alternatives, and a project that is shipping patch releases. What it is not is a document manipulation library, and a project that had been abandoned would have stopped shipping them.
Editorial conclusion
OpenSpout fits a PHP service that exports a report to a spreadsheet with a million rows and cannot hold it in memory, and a team that wants a well maintained successor to the original Spout library without changing the shape of the API. It does not fit a project that needs to read a spreadsheet with heavy formatting intact, since this is a data library rather than a document library, and it does not fit a team that cannot decide between the 4.x and 5.x lines. Verify three things before you adopt it: which line you are on and whether the documentation you are reading matches it, since the homepage link points at the 4.x docs while the default branch is 5.x, what the memory figure means for your own workload, since the under three megabytes claim is about the library's own overhead rather than about the rows you are processing, and whether the legacy Box code in your copy is still Apache licensed, because the licence changes at a specific commit.
Frequently asked questions
What is OpenSpout and what is it a fork of?
It is a community driven fork of box/spout, a PHP library to read and write spreadsheet files in CSV, XLSX and ODS. Unlike other file readers or writers it is capable of processing very large files while keeping the memory usage really low, less than 3MB according to the README.
How do I upgrade from box/spout to OpenSpout?
Two steps. Replace box/spout with openspout/openspout in your composer.json, and replace the Box\Spout namespace with OpenSpout in your code. Upgrading between OpenSpout majors is a separate matter: version 4 introduced new functionality and breaking changes, and the repository has an Upgrade guide document for that.
What licence applies to OpenSpout?
Two of them. The code until and directly descending from commit cc42c1d is copyright of Box, Inc. and licensed under the Apache License, Version 2.0, and the code created, edited and released after that commit is copyright of the openspout organisation and licensed under the MIT License. The repository carries both licence files.
Which version of OpenSpout should I use, and where is the documentation?
The default branch is 5.x and the current releases are on the 5.12.x line, with v5.12.2 published on 2026-10-13. The homepage link in the repository points at the documentation of the 4.x branch, so read the docs directory of the branch you are actually on rather than the linked site.
How is OpenSpout tested?
The Makefile runs the whole toolchain inside a container built from php:8.4.19-cli with composer, pcov and zip. The default target runs the style fixer, PHPStan analysis and coverage, and the coverage target runs PHPUnit and then Infection, the mutation testing tool, limited to the lines that changed with --git-diff-lines and a base branch, and parallelised across the processor count.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/openspout-openspout)Was this useful?