Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dom Crawler Laravel Package

symfony/dom-crawler

DomCrawler eases DOM navigation for HTML and XML documents, letting you query, filter, and extract content with CSS selectors and XPath. Part of the Symfony framework.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. symfony/dom-crawler is a stateless, in-process parsing primitive: PHP's native DOMDocument wrapped in a fluent API for CSS/XPath selection, node traversal, text/attribute/markup extraction, and in-memory form and link navigation. There is no service provider, no configuration surface, no persistence, and no framework coupling. Laravel applications already resolve many symfony/* components transitively through Composer, so this is not an architectural adoption decision — it is a decision about where HTML/XML normalization lives and how tightly domain code couples to the vendor API. Recommendation: adopt as an internal implementation detail behind an application-owned interface (e.g. App\Support\Html\DocumentParser). Domain code, jobs, and API resources should never import Symfony\Component\DomCrawler\* directly. That boundary is the entire exit-cost story if parse behavior or platform constraints shift.

Integration feasibility. High, low effort, near-zero procurement friction. MIT license, no seats, no credentials, no infrastructure. The work is almost entirely around the library: HTTP acquisition with timeouts and retries (Laravel Http), per-host rate limiting, queueing for volume, persistence and deduplication, change detection, and observability (field-level extraction completeness, selector hit rates, drift alerts). A TPM should size the initial thin vertical slice at one sprint for two engineers plus a named owner for ongoing pipeline health — not "add a Composer dependency."

Technical risk. Moderate and well-characterized, concentrated in six areas:

  1. Parse-fidelity fork at v8. v7.4 introduced the native HTML5 parser on PHP 8.4; v8.0 always parses per HTML5 rules and requires PHP ≥ 8.4. Pre-8.0 uses libxml, which is lenient but not HTML5-conformant. Selector results on malformed markup differ across that boundary. Adopting v8 forces a PHP 8.4 floor, and upgrading later can silently change extracted values. Pick a lane deliberately; do not drift into it.
  2. Selector-semantics churn. Recent patch lines fixed matches(), closest(), children() for combinators and positional pseudo-classes, FormField::getLabel() with quoted IDs, textarea content reads, and charsets detected from meta tags. Fixes, but also evidence that edge-case behavior moves in patch releases. Pin versions and regression-test on upgrade.
  3. Silent failure mode. A broken CSS selector returns an empty set, not an exception. This is the dominant production risk and is a product risk, not a library risk: bad data ships quietly.
  4. XML attack surface. CVE-2026-45071 (XXE via addXmlContent()) was patched across 5.4.52 / 6.4.40 / 7.4.12 / 8.0.12 / 8.1.x. Any XML ingestion path — including our own pre-processing — needs external-entity loading disabled and a patch SLA. Treat DomCrawler as a security-relevant dependency.
  5. Static-HTML ceiling. DomCrawler parses server-returned markup only. If targets are JS-hydrated, it is the wrong tool and the fallback is a headless browser (symfony/panther, Playwright), which changes cost, infra, and legal posture by an order of magnitude.
  6. Governance/provenance. The GitHub repo is a read-only split of symfony/symfony; issues, PRs, and security advisories live in the monorepo. Star counts and "dependents: 0" registry metadata understate real-world usage and are not a reliable adoption signal. Backing is the Symfony project and its release train, not a commercial vendor.

Key questions.

  • Are we parsing our own rendered output (safe, controllable) or third-party HTML (drift, ToS, robots, legal review)?
  • Is target content server-rendered or JS-hydrated? Has anyone actually verified, or is that an assumption?
  • What is the data-accuracy SLA, and who is paged when a field silently goes empty?
  • What is the PHP floor today, and when is the 8.4 upgrade planned? That gates v8.
  • Volume and cadence: one-off backfill, hourly, or continuous? Determines queue and rate-limit design.
  • Any PII, credentials, or copyrighted content in scope? Retention and redaction policy?
  • Do we need form submission/link following, or is this read-only extraction? The former introduces side-effect risk.
  • Is there an existing regex/strip_tags/SimpleXML path we are replacing, and do we have a golden-file corpus to prove parity?

Integration Approach

Stack fit. Composer-native and idiomatic for Laravel. A typical Laravel 11/12 app on PHP 8.2–8.3 should target the 7.4 LTS line; only move to 8.x once PHP 8.4 is the platform floor. CSS selector support comes via symfony/css-selector, which is a required dependency; HTML5 parsing for malformed markup benefits from masterminds/html5 on the pre-8.0 path.

Reference shape. An HtmlDocumentParser contract bound in a service provider, with a DomCrawlerAdapter implementation. Extractors are small, named, individually testable classes (ExtractProductPrice, ExtractListingMetadata) that receive a parsed document and return a typed DTO. Configuration — user agent, timeouts, allowed hosts, max document size — lives in config/, not in code. This keeps selectors and vendor calls behind one seam.

Pipeline. Http::withHeaders(...)->timeout(...)->get($url) → assert content type and size ceiling → new Crawler($body, $url) → filter via CssSelector → map to DTO → Laravel validation → persist with source URL, fetched-at timestamp, and a content hash for change detection. Anything beyond trivial volume moves to a queued job with per-host rate limiting and exponential backoff.

Migration path. Do not rewrite. Introduce the adapter, then port one extractor at a time behind a feature flag with shadow mode: run old and new paths in parallel against a fixture corpus plus live sampled URLs, diff the outputs, and promote only when field-level parity is demonstrated. Retire the legacy path after a stable period.

Compatibility work. composer why symfony/dom-crawler before adding it. Explicitly constrain the version in composer.json rather than letting it float, and check that pulling it does not force upgrades to symfony/console, http-foundation, mime, translation, or error-handler, which Laravel pins. Add a CI gate that fails on unattended major-version bumps of symfony/*. Track the Symfony release train: a minor every ~6 months, patches monthly, LTS lines for 6.4 and 7.4.

Sequencing.

  • Phase 0 (1 sprint): spike + fixture corpus + the static-vs-JS answer. Kill criterion: if targets are JS-rendered, stop and re-scope.
  • Phase 1: one production source in shadow mode; observability wired.
  • Phase 2: promote behind flag; drift alerts; rate limits and retries hardened.
  • Phase 3: broaden to remaining sources; formalize selector ownership and review process.

Operational Impact

Maintenance. The library itself is low-touch: monthly patches, two minor bumps a year, and a well-documented deprecation policy. The real maintenance burden is selectors and source behavior, which will rot monthly regardless of library choice. Treat selectors as versioned configuration with named owners and change history — not string literals buried in jobs. Budget roughly 10–20% of one engineer per active source for drift.

Support. No commercial support contract; community and Symfony core team. Internal on-call must own the pipeline end-to-end. Security advisories arrive via Symfony's disclosure process, not through a vendor portal — subscribe and set a patch SLA (e.g. 7 days for high severity on internet-facing ingestion).

Scaling. Parsing is CPU-bound and in-process; scale horizontally with queue workers. DOM trees are memory-hungry — budget roughly 5–10× the markup size per document — so enforce a hard response-size ceiling and cap concurrency per worker. For very large XML (feeds, sitemaps, exports), DomCrawler's whole-document load is the wrong shape; use streaming XMLReader and reserve DomCrawler for navigable, bounded documents. No shared state means no scaling surprises beyond worker count.

Failure modes to instrument and alert on.

  • Silent selector breakage — empty extraction set with a 200 response. Alert on field-level completeness drops, never on HTTP status alone.
  • Charset/mojibake drift — meta-tag detection edge cases; validate encoding explicitly.
  • Parser divergence — libxml vs HTML5 results changing across a v8 upgrade.
  • XXE / entity expansion on XML inputs; disable external entities process-wide.
  • Timeouts, redirect loops, 429/403 bans from insufficient politeness.
  • Memory exhaustion on adversarial or unexpectedly large documents.
  • Side effects from form submission or link following against third-party systems.

Ramp-up. A mid-level Laravel developer is productive with the API in half a day — CSS selectors and XPath are common knowledge. The genuine learning curve is operational discipline: politeness, fixture-based regression testing, drift detection, and treating extraction quality as an SLO. Plan a week for harness and observability, not for the library.

Suggested SLOs. Parse success rate, non-empty extraction rate per field, freshness lag, and a field-completeness error budget that pages the pipeline owner. These are the metrics that make a silent-breakage class of failure visible, which is the single most important control this adoption needs.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo
bernskioldmedia/laravel-harvest
bernskiold/laravel-data-scrubber
bernskiold/laravel-currency-converter
bernskiold/laravel-campaign-monitor
bernskioldmedia/laravel-autotranslate
siberfx/telegram-bot
roy-sandip/laravel-view-extended
gregsphotography/site-builder-core
roy-sandip/laravel-view
anodyne/blade-fluentui-icons
webx-ui/module-catalog-collections