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

Scrapecreators Php Laravel Package

aporat/scrapecreators-php

A Laravel-ready PHP client for the ScrapeCreators API, offering simple, expressive methods for social media scraping endpoints. Fetch profiles, posts, hashtags, and more from supported platforms with clean, framework-friendly integration.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a thin, generated SDK over the ScrapeCreators HTTP API, bundled with a Laravel service provider. Treat it as a typed HTTP client, not a full domain package — there are no Eloquent models, migrations, or persistence opinions.

Install and configure

composer require scrapecreators/php-sdk   # adjust to the real package name
php artisan vendor:publish --tag=scrapecreators-config

Set the API key in .env — check config/scrapecreators.php for the exact key name and for the default cache_max_age (the value that will silently apply to every cacheable endpoint).

Where to look first

  1. config/scrapecreators.php — API key, base URL, timeout, cache_max_age.
  2. spec/openapi.json — this is the source of truth for method names. The 251 resource methods are generated from operation IDs, so when you're unsure whether it's profile() or user() or profileInfo(), read the spec (or the generated resource class) rather than guessing.
  3. The exception classes — the type you catch determines the UX you show, so read RestrictedException, NotFoundException, and InsufficientCreditsException before writing your first controller.

First use case — a cached profile lookup in a controller or job:

use ScrapeCreators\Exceptions\NotFoundException;

try {
    $response = ScrapeCreators::tiktok()->profile($handle); // method name per spec
    $profile  = $response->data();
} catch (NotFoundException $e) {
    abort(404);
}

Note that profile() returning without throwing already tells you the account exists and is public — those cases are classified out of the HTTP 200 envelope for you.

Implementation Patterns

Response handling: data() for the payload, get() for one field. data() gives you the decoded payload to hand to a transformer or json_encode. get('user.stats.followers') with a dot path avoids a chain of ?? null. The ArrayAccess implementation is convenient for quick reads inside Blade/views; prefer data() when you're passing structured data further down the stack.

Cache-aware reads (the default path). By default the SDK applies cache_max_age, so calls can be served from ScrapeCreators' cache rather than a fresh scrape. Design your UI around that being normal:

$response = ScrapeCreators::instagram()->profile($username);

if ($response->isCached()) {
    // show "as of {cachedAt}" — it's honest and cheap
}

This makes repeated page views essentially free and fast. Only reach for a live scrape when the user explicitly asks to refresh.

Force a live scrape deliberately. Client::LIVE (passed as the cache-max-age argument) bypasses the cache. Use it for explicit "refresh" buttons, cron jobs where freshness is the whole point, and reconciliation flows — not in loops or page loads:

ScrapeCreators::tiktok()->profile($handle, ScrapeCreators::LIVE);

Wrap these behind your own service method so a stray live call can't get copy-pasted into a hot path.

Map exceptions to user-facing outcomes in one place. Rather than scattering try/catch across controllers, write a single mapper (or a rescue() helper) that turns the exception type into a result:

try {
    return $this->client->youtube()->channel($id);
} catch (RestrictedException $e) {
    // $e->isPrivate() / $e->isAgeRestricted()
} catch (NotFoundException $e) {
    // account genuinely does not exist
} catch (InsufficientCreditsException $e) {
    // alert ops, not the user
} catch (RateLimitException $e) {
    // backoff
} catch (ScrapeCreatorsException $e) {
    // AuthenticationException, UnavailableException,
    // InvalidRequestException, InvalidResponseException land here
}

Catch the specific types first and the base class last; the base class gives you getResponse() and the decoded envelope for logging. Never surface getMessage() from the SDK to end users — it's upstream-facing.

Budget credits in queue jobs. creditsCharged() and creditsRemaining() are the hooks for cost control. Log both on every call in a job, and alarm when creditsRemaining() trends down faster than your call volume suggests — that's the signature of a retry loop or an accidental LIVE in a loop.

Queue anything that scrapes. A live scrape is a multi-second upstream call; do it in a job with $tries and backoff(). On RateLimitException, release with backoff rather than failing. On InsufficientCreditsException, fail permanently — retrying is pointless and burns nothing but log space.

Fall back to the raw client for uncovered endpoints. The 27 resources cover the API as of the current spec, but new endpoints appear between SDK releases. get() / post() take any path, so you can ship against a brand-new endpoint immediately and swap in the generated method after the next release.

Testability. There's no documented fake/recording layer in this release. Two options: if the client sits on Laravel's HTTP client, Http::fake() works; if not, bind the client behind your own interface in a service provider and swap in a stub in tests. Also be aware that caching makes tests non-deterministic — flush the relevant cache store in setUp() or force Client::LIVE in the test path.

Gotchas and Tips

HTTP 200 does not mean success. Missing, private, restricted, and age-gated accounts come back as HTTP 200 with an envelope the SDK classifies into NotFoundException / RestrictedException. If you check status codes yourself anywhere in your code, you'll get it wrong. Always let the exception propagate and handle by type.

"It's returning stale data" is almost always cache_max_age. A newly changed bio not showing up, a follower count that hasn't moved — check isCached() first before assuming the scraper is broken. If you need freshness guarantees in a specific flow, force LIVE there rather than lowering the global default, which quietly multiplies your credit usage across the whole app.

Client::LIVE is the biggest accidental-cost footgun. It's a constant that looks like harmless configuration. Grep for it before you ship, and keep it out of anything inside a loop.

Distinguish null from "not there." get('path.to.field') returning null could mean the key is absent or the value is genuinely null. If the distinction matters (e.g. private accounts where follower counts are stripped), check the parent object's presence too.

Prefer get($path, $default) over isset($response['a']['b']). ArrayAccess implementations rarely support nested isset() the way arrays do; the dot-path getter with a default is the reliable form.

Pin the version and read the spec on upgrade. This is 0.x with 251 generated methods. Method names come from OpenAPI operation IDs, and regenerating against a changed spec can rename things without it being called a breaking change. Treat minor bumps as potentially breaking for method signatures, run your test suite, and diff spec/openapi.json when something goes missing.

InvalidResponseException means the upstream shape changed. The decoded envelope is attached — log it verbatim, because it's the artifact you'll need to reproduce and report. Don't swallow it into a generic "something went wrong" toast.

AuthenticationException on a working app usually means config caching. After rotating the key: update .env, then php artisan config:cache again (or config:clear locally). Deployment pipelines that cache config before injecting env vars will fail here.

Extension points, in order of preference: raw get()/post() for a not-yet-generated endpoint → regenerate via composer generate against an updated spec (contribute it back) → wrap the whole client behind your own service class if you need to swap providers or add cross-cutting retry/logging logic in one place.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package