andreyco/instagram
A PHP client for the Instagram API that wraps authentication and common endpoints for users, media, comments, and likes. It provides a simple, object-oriented interface for making requests and handling responses in PHP applications.
composer require andreyco/instagram. Then read, in order: README.md (the only usage docs), composer.json (PSR-4 namespace and PHP/extension requirements), and src/ — the client class plus the Exception/ directory. Look for an examples/ folder; it is the fastest way to see the intended OAuth loop.api.instagram.com), not the Facebook Graph/Basic Display API. That API was retired, so treat the package as legacy-maintenance tooling or a reference implementation, not something to build new features on.use Andreyco\Instagram\Client;
$client = new Client([
'client_id' => env('INSTAGRAM_CLIENT_ID'),
'client_secret' => env('INSTAGRAM_CLIENT_SECRET'),
'redirect_uri' => env('INSTAGRAM_REDIRECT_URI'),
'scope' => ['basic', 'public_content'],
]);
$client->getLoginUrl(), handle the callback, exchange the code for a token (getAccessToken($code); older docs/forks call it getOAuthToken()), persist the token + user id, then construct an authenticated client ('access_token' => $token) and call a cheap endpoint such as users/self to prove the flow end to end.Bind it once, inject it everywhere. A Laravel singleton keeps configuration in one place and makes the client swappable in tests:
// AppServiceProvider::register()
$this->app->singleton(Client::class, fn () =>
new Client(config('services.instagram'))
);
Split the OAuth flow into two controllers. redirect() returns redirect()->away($client->getLoginUrl()); callback() exchanges the code, stores access_token (and user->id, user->username) on the user record, and redirects home. Never keep tokens in the session for long-lived use — persist them encrypted.
Per-user clients for multi-account apps. The singleton holds app credentials only; build a short-lived authenticated instance per request/job with the stored token, or call setAccessToken($token) before each batch.
Endpoint calls follow a resource/verb shape. Use get(), post(), delete() with a path and query array, and always read the data envelope:
$page = $client->get('users/self/media/recent', ['count' => 24]);
foreach ($page->data as $media) { /* ... */ }
Paginate with next_max_id, not offsets. Loop while $page->pagination->next_max_id is set, passing it back as max_id. Keep it as a string — casting to int truncates it and silently returns page one forever.
Cache reads, queue writes. Wrap feed/profile reads in Cache::remember() with a short TTL; push likes/comments/follows into queued jobs so a slow or rate-limited API never blocks a request.
Normalize errors at the boundary. Catch Andreyco\Instagram\Exception\ApiException, log code + message + endpoint, and convert to your app's domain exception. For anything the package does not wrap, check the raw response's meta->code because some versions return error payloads instead of throwing.
Test behind an interface. The client does its own cURL, so mocking is awkward. Define a small InstagramGateway contract, implement it with this client, and bind a fake in tests — this also gives you a migration seam when you move to the Graph API.
dev-master.client_id/client_secret/redirect_uri in this package vs apiKey/apiSecret/apiCallback in cosenary/Instagram-PHP-API. Copy the keys from the README of the version you actually installed.data arrays while the call itself "succeeds." Check app mode before chasing pagination issues.verify_peer settings surface as generic transport exceptions, not API errors.How can I help you explore Laravel packages today?