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

Flaresolverr Bundle Laravel Package

pbxg33k/flaresolverr-bundle

A Symfony bundle that integrates FlareSolverr, the proxy service for bypassing Cloudflare and similar anti-bot challenges. It wires the solver into your app via service configuration and dependency injection, so protected pages can be fetched programmatically from your PHP project with minimal setup...

View on GitHub
Deep Wiki
Context7

Getting Started

Know what you're installing first. pbxg33k/flaresolverr-bundle is a Symfony bundle, not a Laravel package. It wraps FlareSolverr, a sidecar service that drives a headless Chromium instance to clear Cloudflare/bot challenges. There is no Laravel service provider, no auto-discovery, no facade. Treat 0.0.3 as the first usable release and plan accordingly.

  1. Stand up the service before touching PHP. Nothing in this package works without a running FlareSolverr:
    docker run -d --name flaresolverr -p 8191:8191 \
      -e LOG_LEVEL=info ghcr.io/flaresolverr/flaresolverr:v3.3.6
    curl -X POST http://localhost:8191/v1 \
      -H 'Content-Type: application/json' \
      -d '{"cmd":"request.get","url":"https://example.com","maxTimeout":60000}'
    
    Pin the FlareSolverr Docker tag explicitly — latest moves and has broken the wire format before.
  2. Read the bundle's source, not just the README. With no Flex recipe and the config generator still on the TODO list (see 0.0.3 notes), the authoritative reference is vendor/pbxg33k/flaresolverr-bundle/ — the client class and its option array are what you actually need.
  3. Decide your integration path. In a Laravel app you have two realistic options:
    • Thin path (recommended for most teams): skip the bundle entirely and call the REST API with Illuminate\Support\Facades\Http. Use the bundle as documentation for the request/response shape.
    • Full path: install the bundle's dependencies (symfony/http-client, symfony/options-resolver) and bind the client class manually in a service provider. Expect friction — see Gotchas.
  4. First use case: a queued job that fetches a Cloudflare-protected page and returns the HTML, so you can validate the whole chain (container → client → parsed body) before wiring it into anything real.

Implementation Patterns

Service-provider binding (thin path). Keep the HTTP details in one place so the rest of the app never sees FlareSolverr's envelope:

// config/flaresolverr.php
return [
    'base_url'    => env('FLARESOLVERR_URL', 'http://flaresolverr:8191/v1'),
    'timeout'     => (int) env('FLARESOLVERR_TIMEOUT', 90),
    'max_timeout' => (int) env('FLARESOLVERR_MAX_TIMEOUT', 60000),
    'enabled'     => (bool) env('FLARESOLVERR_ENABLED', false),
];
final class FlareSolverrClient
{
    public function get(string $url): string
    {
        $res = Http::timeout(config('flaresolverr.timeout'))
            ->acceptJson()
            ->post(config('flaresolverr.base_url'), [
                'cmd'        => 'request.get',
                'url'        => $url,
                'maxTimeout' => config('flaresolverr.max_timeout'),
            ])
            ->throw()
            ->json();

        abort_unless(($res['status'] ?? null) === 'ok', 502, $res['message'] ?? 'solver failed');

        return $res['solution']['response'];
    }
}

Bind it as a singleton and inject it — never call Http::post to FlareSolverr inline from a controller.

Always queue the solve. A cold challenge can take 10–60 seconds. A synchronous solve inside a web request will blow through PHP-FPM/Octane worker limits and your users' patience. Dispatch a job, return 202, notify on completion.

Reuse cf_clearance where you legally and technically can. The solution.cookies array is the prize. Persist it with its user-agent and egress IP, then replay it through Guzzle for follow-up requests. Cheaper by an order of magnitude than re-solving per URL.

POST and form flows. request.post takes postData as a URL-encoded string. Keep it explicit rather than passing an array, since the service expects the raw body:

['cmd' => 'request.post', 'url' => $url, 'postData' => http_build_query($data), 'maxTimeout' => 60000]

Serialize concurrency. Chromium is memory-hungry: one solve at a time per FlareSolverr container. Use ->onQueue('solver') with a single worker, or Redis::funnel()/WithoutOverlapping middleware.

Swap-seam. Define a PageFetcher interface (fetch(string $url): string) with FlareSolverrFetcher and PlainHttpFetcher implementations, chosen by config('flaresolverr.enabled'). That flag is your kill switch, your local-dev bypass, and your future migration path.

Health check. On boot or in a scheduled command, hit /v1 with a trivial request and cache the result. Fail the deploy loudly rather than discovering the sidecar is unreachable at 2 a.m.

Gotchas and Tips

The config file still isn't generated. This is the headline caveat of 0.0.3 — the release notes explicitly list "Generate a proper config/package/flare_solverr.yaml" as outstanding, meaning it currently requires manual actions. If you follow the full path, create the YAML by hand from the bundle's Resources/ examples and re-verify key names on upgrade. Under Laravel this is moot: use config/flaresolverr.php and your own binding.

"Finalize first release" is not a stability guarantee. 0.0.3 is the first release with the rough edges sanded off, but it is still 0.x. Composer constraints follow ^0.0.3 semantics where ^0.0.3 won't pick up 0.1. Pin the exact version (0.0.3) and read the changelog before any bump — pre-1.0 allows breaking changes at any patch level, and "final touches" can mean renamed option keys.

You cannot register a Symfony bundle in Laravel's container. The Bundle class, DependencyInjection extension, and YAML config are all inert here. The client class and option resolver are reusable; the wiring is not. Budget an hour for the first integration, or take the thin path.

Timeouts are the #1 failure. Laravel's HTTP client defaults to 30s; a solve often needs more. Set ->timeout(90) on the request and maxTimeout in the payload, and make sure max_execution_time, queue $timeout, and any proxy/load-balancer idle timeouts all exceed both. A load balancer timing out at 60s while your job waits 90s is a classic.

Docker networking. http://localhost:8191 works from your host but not from inside an app container. Use the compose service name (http://flaresolverr:8191) and keep it in env, not hard-coded.

Challenge detection is a moving target. FlareSolverr's success depends on Chromium/undetected-chromedriver patches matching whatever Cloudflare deployed that week. Pin the container image, watch for status: "error" with retry-after hints, and don't blindly retry — each retry burns CPU and can trip rate limits.

Cookies are bound to IP + user agent. cf_clearance is worthless if your egress IP rotates or the UA differs. Pin the UA across the solve and the replay; use a sticky proxy or none at all.

Handle the non-200s deliberately. FlareSolverr returns status: "error" in the JSON body on failure (still HTTP 200), and 503 when overloaded. Check the envelope, not just the HTTP code — ->throw() alone will miss failed solves.

Debugging. Set LOG_LEVEL=debug on the container to see challenge pages it captured; log the request URL and solution.cookies names (not values) on your side. Never log full solution bodies in production — they can contain session tokens and personal data.

Compliance is a real gotcha, not boilerplate. Bot-protection circumvention may violate the target site's terms of service and, depending on jurisdiction, computer-misuse statutes. Gate the whole feature behind an explicit config flag, document the approved use cases, and get sign-off before it ships.

Extension points worth knowing. The sessions API (sessions.create / sessions.destroy) lets you reuse a warm browser context across a batch — far faster than independent solves. And because the client is a plain class, the cleanest extension point in a Laravel codebase is your own PageFetcher interface, which lets you migrate to a different solver vendor with a one-line container rebind.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager