An expressive, driver-based PHP API for local and remote document parsers.

Maintainers

Package info

github.com/shipfastlabs/parsel

pkg:composer/shipfastlabs/parsel

Transparency log

Fund package maintenance!

pushpak1300

Statistics

Installs: 3 860

Dependents: 0

Suggesters: 0

Stars: 339

Open Issues: 1

v1.0.0 2026-08-05 11:19 UTC

This package is auto-updated.

Last update: 2026-08-05 11:25:34 UTC


README

Parsel

Tests Latest Version License

Parsel provides one expressive PHP API for document parsing, backed by interchangeable drivers. Version 1.0 includes local LiteParse and AnyDoc drivers and public contracts for custom or future hosted providers.

use Shipfastlabs\Parsel;

$markdown = Parsel::file('report.pdf')->markdown(); // LiteParse by default

$markdown = Parsel::driver('anydoc')
    ->file('report.docx')
    ->markdown();

Parsel requires PHP 8.4 or greater.

Installation

composer require shipfastlabs/parsel

Install only the parser you use. With no --driver, the installer installs LiteParse:

vendor/bin/parsel-install
vendor/bin/parsel-install --driver=anydoc
vendor/bin/parsel-install --driver=all

LiteParse supports npm, pnpm, bun, pip, and cargo. AnyDoc supports npm, pnpm, and bun and requires Node.js 20 or newer.

vendor/bin/parsel-install --driver=liteparse --manager=cargo
vendor/bin/parsel-install --driver=anydoc --manager=npm
vendor/bin/parsel-install --driver=liteparse --with-system-dependencies

vendor/bin/parsel-install-lit remains as a compatibility alias.

Drivers and capabilities

Capability LiteParse AnyDoc
Markdown Yes Yes
Plain text Yes No
Structured pages and coordinates Yes No
Lazy pages Yes No
Screenshots Yes No
OCR Yes No

Calling an unavailable operation throws UnsupportedCapabilityException before the provider is executed. Parsel does not derive fake structured data or plain text from AnyDoc Markdown.

LiteParse remains the default driver, so existing basic calls continue to work:

$text = Parsel::file('invoice.pdf')->text();
$document = Parsel::file('invoice.pdf')->parse();
$array = Parsel::file('invoice.pdf')->toArray();

Select AnyDoc explicitly or change the process-wide default:

Parsel::driver('anydoc')->file('book.epub')->markdown();

Parsel::defaultDriver('anydoc');
Parsel::file('book.epub')->markdown();

For dependency injection and long-running applications, use an instance:

use Shipfastlabs\Parsel\ParselManager;

$parsel = new ParselManager;
$markdown = $parsel->driver('anydoc')->file('report.docx')->markdown();

Sources and common options

Both drivers accept paths and raw bytes. Byte sources require an extension so signature-less formats such as CSV can be identified reliably.

$markdown = Parsel::file('/path/to/report.pdf')->markdown();
$markdown = Parsel::bytes($uploadedBytes, 'pdf')->markdown();

$markdown = Parsel::driver('anydoc')
    ->bytes($csvBytes, 'csv')
    ->withProviderOptions(['format' => 'csv'])
    ->markdown();

Timeout is portable across drivers:

Parsel::file('report.pdf')->withTimeout(120)->markdown();

save() selects the corresponding capability from the extension. Both drivers support .md and .markdown; LiteParse additionally supports .txt and .json.

Parsel::driver('anydoc')->file('report.docx')->save('report.md');
Parsel::file('report.pdf')->save('report.json');

Provider options

Provider-specific behavior belongs in withProviderOptions(). It accepts a typed fluent object or a strict associative array.

use Shipfastlabs\Parsel\Options\LiteParseOptions;

$options = LiteParseOptions::make()
    ->pageRange(1, 5)
    ->page(10)
    ->withOcr(language: 'eng', workers: 8)
    ->withDpi(300)
    ->preserveSmallText();

$document = Parsel::file('invoice.pdf')
    ->withProviderOptions($options)
    ->parse();

LiteParse options include page selection, maximum pages, OCR settings, DPI, small-text preservation, passwords, Markdown images and links, headers and footers, and a binary override.

use Shipfastlabs\Parsel\Enums\ImageMode;

$markdown = Parsel::file('report.pdf')
    ->withProviderOptions(
        LiteParseOptions::make()
            ->withoutOcr()
            ->withImages(ImageMode::Embed, '/path/to/images')
            ->withoutLinks()
            ->keepHeadersAndFooters()
    )
    ->markdown();

AnyDoc supports explicit input format and binary overrides:

use Shipfastlabs\Parsel\Options\AnyDocOptions;

$markdown = Parsel::driver('anydoc')
    ->file('data.csv')
    ->withProviderOptions(
        AnyDocOptions::make()->format('csv')
    )
    ->markdown();

Array keys are validated, so typos fail early. For a newly released upstream CLI flag, use the explicit escape hatch:

$options = LiteParseOptions::make()->option('new-upstream-flag', 42);
$options = AnyDocOptions::make()->option('new-upstream-flag');

Structured LiteParse output

$document = Parsel::file('document.pdf')->parse();

echo $document->text;
echo $document->pageCount();

foreach ($document->pages as $page) {
    foreach ($page->items as $item) {
        echo "{$item->text} @ ({$item->x}, {$item->y})\n";
    }
}

Stream large documents without decoding the complete page array:

foreach (Parsel::file('large.pdf')->lazyPages() as $page) {
    echo $page->text;
}

Screenshots require an existing destination directory:

$files = Parsel::file('document.pdf')
    ->withProviderOptions(LiteParseOptions::make()->pageRange(1, 5)->withDpi(200))
    ->screenshots('/path/to/screenshots');

Binary resolution

Each local driver resolves its executable in this order:

  1. The typed or array provider option binary.
  2. PARSEL_LITEPARSE_BINARY or PARSEL_ANYDOC_BINARY.
  3. lit or anydoc on PATH.

PARSEL_LIT_BINARY remains a fallback for LiteParse during the 1.0 migration.

Custom drivers

Implement the minimal Driver contract for Markdown, then opt into additional capability contracts only when the provider supports them.

use Shipfastlabs\Parsel;
use Shipfastlabs\Parsel\Contracts\Driver;
use Shipfastlabs\Parsel\ParseRequest;
use Shipfastlabs\Parsel\ParselManager;

Parsel::extend('company-api', function (ParselManager $manager): Driver {
    return new CompanyApiDriver;
});

$markdown = Parsel::driver('company-api')->file('report.pdf')->markdown();

Drivers are resolved lazily and cached by the manager. Implement TextDriver, StructuredDocumentDriver, LazyPageDriver, or ScreenshotDriver to add those operations. A remote driver may use any HTTP client and does not need to depend on Parsel's CLI process infrastructure.

Testing

Parsel::fake() swaps the shared local process runner and matches canned responses against command substrings:

$fake = Parsel::fake([
    '--format json' => file_get_contents(__DIR__.'/fixtures/lit-output.json'),
    'anydoc' => '# Converted document',
]);

$document = Parsel::file('invoice.pdf')->parse();
$markdown = Parsel::driver('anydoc')->file('report.docx')->markdown();

expect($fake->ranCount())->toBe(2);

See UPGRADE.md when moving from Parsel 0.x.

Development

composer test
vendor/bin/pest --group=integration

Credits

Parsel is maintained by Shipfastlabs and released under the MIT license.