5 best CSV import packages for Laravel in 2026
5 best CSV import packages for Laravel in 2026
Search "CSV import Laravel" and you will find dozens of tutorials that start with fgetcsv() and end with "for anything more complex, use a package." Fair enough. But which package?
The Laravel ecosystem has five serious options for handling CSV imports, and they solve genuinely different problems. Some parse files. Some process data. One gives your users a full import wizard. Picking the wrong one means either over-engineering a simple task or rebuilding half the package's functionality yourself when the requirements grow.
This is not a ranked list. There is no "#1 pick." The right tool depends on whether you are writing a one-off artisan command or shipping a user-facing import feature in a SaaS product. For each package, we cover what it does, show real code, call out the limitations, and tell you when it fits.
For a deeper look at the approaches themselves (including raw PHP), see The complete guide to CSV imports in Laravel.
#1. Laravel Excel
The workhorse. 146M+ Packagist downloads.
Laravel Excel (maatwebsite/excel) has been the default answer to "how do I import a spreadsheet in Laravel" for over a decade. It handles CSV, XLSX, ODS, and TSV files. It handles exports too, which none of the other import-focused packages do.
The API uses a concern-based architecture. You create an import class, implement interfaces for the capabilities you need, and call Excel::import():
use App\Models\Contact;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Illuminate\Contracts\Queue\ShouldQueue;
class ContactImport implements ToModel, WithHeadingRow, WithValidation, WithChunkReading, ShouldQueue
{
public function model(array $row): Contact
{
return new Contact([
'first_name' => $row['first_name'],
'email' => $row['email'],
]);
}
public function rules(): array
{
return [
'email' => ['required', 'email'],
];
}
public function chunkSize(): int
{
return 1000;
}
}
Then in your controller:
Excel::import(new ContactImport, $request->file('csv'));
Each concern adds a capability: WithBatchInserts for grouped database writes, SkipsOnFailure to collect errors without halting, WithEvents for lifecycle hooks. The architecture is flexible and well-documented.
#Best for
- Scheduled imports from known file formats (S3 bucket syncs, nightly vendor exports)
- Artisan commands for data migrations
- Any import where a developer controls the trigger and the column structure is predictable
- Projects that also need XLSX/CSV export
#Limitations
- No user interface. Column mapping, error review, and progress tracking are on you to build.
- Validation errors are collected after the fact. There is no step where users fix errors before data touches the database.
- Relationship resolution (matching a "Company" column to existing records) requires custom code inside
model(). - The XLSX reader depends on PhpSpreadsheet, which adds significant memory overhead for large files.
For a deep comparison of where Laravel Excel ends and a wizard begins, see Laravel Excel vs Tapix.
#2. League CSV
The parser. 168M+ Packagist downloads.
League CSV is not a Laravel package. It is a PHP library for reading and writing CSV files, and it is excellent at that single job. No Eloquent integration, no queue processing, no validation layer. Just fast, memory-efficient CSV parsing with a clean API.
use League\Csv\Reader;
$csv = Reader::createFromPath($path, 'r');
$csv->setHeaderOffset(0);
foreach ($csv->getRecords() as $record) {
Contact::create([
'first_name' => $record['first_name'],
'email' => $record['email'],
]);
}
League CSV also ships a Writer class, stream-based reading for large files, and a tab completion API for filtering and transforming records before you process them. It handles encoding detection, BOM handling, and delimiter guessing -- the low-level CSV edge cases that trip up fgetcsv().
#Best for
- When you need precise control over CSV parsing without framework opinions
- Piping CSV data between systems (read from one source, transform, write to another)
- Projects that are not Laravel-specific or want minimal dependencies
- Building your own import abstraction on top of a reliable parser
#Limitations
- No Laravel-specific features. No Eloquent concerns, no queue integration, no validation rules.
- You write the entire import pipeline yourself: chunking, error handling, progress tracking.
- CSV only -- no XLSX, ODS, or other spreadsheet formats.
- No UI components of any kind.
League CSV is a foundation, not a solution. If you are building a custom import system and want a parser you can trust, this is the one. If you want something that handles the full pipeline, keep reading.
#3. Spatie Simple Excel
The pragmatist. 10M+ Packagist downloads.
Spatie Simple Excel (spatie/simple-excel) wraps OpenSpout in a Laravel-friendly API. OpenSpout reads XLSX, CSV, and ODS files with constant memory usage regardless of file size -- it streams rows instead of loading the entire file into memory. Simple Excel adds a fluent API on top:
use Spatie\SimpleExcel\SimpleExcelReader;
SimpleExcelReader::create($path)
->useHeaders(['first_name', 'last_name', 'email'])
->trimHeaderToLetters()
->getRows()
->each(function (array $row) {
Contact::create([
'first_name' => $row['first_name'],
'email' => $row['email'],
]);
});
The getRows() method returns a LazyCollection, so you can chain ->chunk(), ->filter(), and other collection methods without loading 100K rows into memory. Writing is just as simple:
use Spatie\SimpleExcel\SimpleExcelWriter;
SimpleExcelWriter::create('contacts.xlsx')
->addRow(['first_name' => 'John', 'email' => 'john@example.com']);
#Best for
- Reading large XLSX files without memory issues (OpenSpout streams rows, PhpSpreadsheet loads the whole file)
- Simple imports where you want a clean API without the concern-based architecture of Laravel Excel
- Projects that value minimal configuration --
create()+getRows()+ done
#Limitations
- No built-in validation, queue processing, or chunked job dispatching. You handle that yourself.
- No column mapping or user-facing UI.
- Fewer features than Laravel Excel (no formula support, no cell formatting, no multi-sheet exports with styling).
- The tradeoff is explicit: less magic, less capability, less complexity.
Simple Excel is the right choice when Laravel Excel feels like overkill but fgetcsv() feels too raw. It sits in a pragmatic middle ground.
#4. Filament Import Action
The built-in. Ships with Filament.
If your application already runs Filament, you have a CSV import capability built into the framework. Import Action provides a column mapping modal, background queue processing, and a notification when the import completes -- all without adding a package:
use App\Filament\Imports\ContactImporter;
use Filament\Actions\ImportAction;
ImportAction::make()
->importer(ContactImporter::class)
The importer class defines columns with ImportColumn::make(), maps them to model attributes, and lets users match CSV headers to your fields in a modal before processing starts.
#Best for
- Filament admin panels where imports are an occasional admin task
- Simple imports with predictable column structures
- Teams that want zero additional dependencies
#Limitations
- No inline error correction. Validation errors are reported after the import runs. Users cannot fix row 47's bad email address inside the application -- they download a failure report, fix the source file, and re-upload.
- No review step. There is no screen where users see all their data, confirm it looks right, and then execute. It is map-and-go.
- Performance degrades with large files. The modal-based mapping and single-job processing work well for a few thousand rows but struggle past that.
- No relationship wizard. Linking a "Company" column to existing
Companyrecords, or creating missing ones, requires custom code. - Filament-only. If your application does not use Filament, this is not an option.
For a detailed breakdown of where Import Action fits and where it does not, see Filament Import Action: when it's enough and when you need more.
#5. Tapix
The full-stack import wizard. Self-hosted.
Tapix is a different kind of package. Where the other four handle file parsing and data processing, Tapix is a complete import experience: upload, column mapping, validation review, error correction, relationship linking, and queue-powered execution in a 4-step wizard.
The core abstraction is an importer that defines typed fields:
use Tapix\Core\Fields\ImportField;
use Tapix\Core\Fields\ImportFieldCollection;
use Tapix\Core\Fields\FieldType;
use Tapix\Core\Enums\MatchBehavior;
public function fields(): ImportFieldCollection
{
return ImportFieldCollection::make([
ImportField::make('first_name')
->required()
->guess(['first name', 'fname', 'given name']),
ImportField::make('email')
->type(FieldType::Email)
->required(),
ImportField::make('company')
->relationship(
name: 'company',
model: Company::class,
matchBy: ['name'],
behavior: MatchBehavior::MatchOrCreate,
),
]);
}
From this definition, users get:
- Upload -- drag and drop a CSV, parsed in the background.
- Map -- auto-matched columns with manual correction. The
guess()aliases handle "First Name" vs "fname" vs "given_name" without developer intervention. - Review -- validation errors shown inline. Users click a cell, fix the value, and continue. No download-fix-reupload cycle. For more on this pattern, see Handling CSV validation errors before they hit your database.
- Execute -- chunked queue jobs with live progress. Relationships resolve according to their configured
MatchBehavior.
Tapix ships as a Filament plugin (three lines in your panel provider) and as standalone Livewire components for non-Filament Laravel applications.
#Best for
- User-facing imports where the person uploading the file is not a developer
- SaaS onboarding flows where customers bring data from different sources with unpredictable column names
- Applications where data quality matters and errors need to be caught before they hit the database
- Projects with relational data (contacts with companies, products with categories, orders with customers)
- Multi-tenant applications (built-in tenant scoping)
#Limitations
- Laravel and Livewire only. No Inertia or API-only support yet.
- Paid license ($59-$299/yr depending on plan).
- Newer than the other packages on this list -- released in 2026.
- Does not handle exports (pair it with Laravel Excel or Spatie Simple Excel for that).
Full disclosure: this is our product. We included it because a listicle about CSV import packages for Laravel that omits the only one with a user-facing wizard would be incomplete. The comparisons above are accurate. If your imports are developer-triggered with predictable file formats, the free options are the right choice.
#Comparison matrix
| Laravel Excel | League CSV | Spatie Simple Excel | Filament Import Action | Tapix | |
|---|---|---|---|---|---|
| CSV parsing | Yes | Yes | Yes | Yes | Yes |
| XLSX support | Yes | No | Yes | Yes | Yes |
| Column mapping UI | No | No | No | Yes (modal) | Yes (full wizard) |
| Inline error correction | No | No | No | No | Yes |
| Relationship linking | Manual | Manual | Manual | Manual | Built-in wizard |
| Queue processing | Yes | Manual | Manual | Yes | Yes |
| Large file support | Chunked (memory heavy for XLSX) | Streaming | Streaming (OpenSpout) | Limited | Chunked + streaming |
| Export support | Yes | Yes (writer) | Yes | No | No |
| UI framework | None | None | None | Filament only | Filament + Livewire |
| Price | Free | Free | Free | Free (with Filament) | $59-$299/yr |
| Packagist downloads | 146M+ | 168M+ | 10M+ | Ships with Filament | New |
#How to choose
The decision tree is shorter than it looks:
Do you need to parse a CSV in a script, command, or background job with no user interaction? Use Laravel Excel for full-featured imports with validation and queue support, Spatie Simple Excel for memory-efficient streaming with a minimal API, or League CSV if you want a pure parser with no framework coupling.
Do you have a Filament admin panel and need a quick import for internal users? Start with Filament's built-in Import Action. If you hit its limits (no review step, no inline editing, relationship complexity), move to Tapix's Filament plugin.
Are your users the ones importing data, with unpredictable file formats and varying data quality? That is the problem Tapix was built to solve. The column mapping, validation review, and relationship wizard are the parts you would otherwise spend 3-4 weeks building yourself.
Do you need exports? Laravel Excel or Spatie Simple Excel. Tapix and Filament Import Action handle imports only.
These packages are not mutually exclusive. Many applications use Laravel Excel for scheduled backend imports and Tapix for the customer-facing wizard. They share no classes, no configuration, and no database tables.
For more on the build-vs-buy decision for import UIs, see The hidden cost of building your own CSV importer.