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

Instagram Laravel Package

nineteensquared/instagram

A Laravel package for integrating Instagram into your PHP applications. Fetch and display Instagram feeds, handle API authentication, and pull Instagram content into your projects through a simple, expressive interface.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

composer require nineteensquared/instagram
php artisan vendor:publish --tag=instagram-config   # check the provider for the exact tag

Then add the OAuth credentials to .env (the addon's config file will tell you the exact keys — typically INSTAGRAM_CLIENT_ID / INSTAGRAM_CLIENT_SECRET / INSTAGRAM_REDIRECT_URI):

INSTAGRAM_CLIENT_ID=xxxxxxxxxxxx
INSTAGRAM_CLIENT_SECRET=xxxxxxxxxxxx
INSTAGRAM_REDIRECT_URI=https://yoursite.test/instagram/callback

Where to look first, in this order

  1. src/ServiceProvider.php — confirms the Antlers tag name, the config namespace, and whether the control-panel settings screen is registered.
  2. config/instagram.php — cache TTL, number of posts, and where the access token is stored.
  3. routes/ — the OAuth callback route you must whitelist in the Meta app dashboard.
  4. Control Panel → Tools/Addons → Instagram. If a "Connect" button exists, use it rather than hand-generating tokens; the addon will do the short-lived → long-lived exchange for you.

First use case

You almost certainly want this for one thing: a footer or homepage "latest from Instagram" strip. Drop the tag in a partial, cache it, and move on:

{{ instagram limit="6" cache="60" }}
  <a href="{{ permalink }}" target="_blank" rel="noopener">
    {{ if media_type == "VIDEO" }}
      <img src="{{ thumbnail_url }}" alt="">
    {{ else }}
      <img src="{{ media_url }}" alt="">
    {{ /if }}
  </a>
{{ /instagram }}

Confirm the variable names against the raw response (the Basic Display API returns media_url, thumbnail_url, permalink, caption, media_type, timestamp) — most bugs here are just typo'd keys, not addon bugs.

Implementation Patterns

Wrap it in a partial, never inline. A tag like this makes a live HTTP call on every render unless it hits cache. Put it in resources/views/partials/instagram.antlers.html, reference it once from layout/footer, and let the addon's cache do the work. Rendering it inside a Replicator loop or a collection listing is how you burn through the 200-calls-per-hour limit in a single page load.

Prefer the tag's cache attribute over Antlers {{ cache }}. Addon-level caching stores the normalized array and survives template edits; Antlers caching stores rendered HTML and gets invalidated when you touch the partial. For a feed that changes a few times a week, cache="360" (minutes) is a sane starting point.

Blade / Livewire escape hatch. If you're not in Antlers land, Statamic exposes tag rendering programmatically:

$feed = \Statamic\Facades\Antlers::parse('{{ instagram limit="6" }}...{{ /instagram }}');
// or, if the addon ships a repository class:
app(\NineteenSquared\Instagram\Instagram::class)->feed(6);

Check src/ for a non-tag class before writing markup-in-strings — addons of this vintage often have a thin service you can inject.

Handle the empty state explicitly. OAuth tokens expire. Your template should degrade to something that doesn't look broken:

{{ instagram limit="6" }}
  {{ if no_results }}
    <p>Follow us on Instagram →</p>
  {{ else }}
    ...
  {{ /if }}
{{ /instagram }}

Token lifecycle as a scheduled concern. Long-lived Basic Display tokens last ~60 days. Either schedule an artisan command that refreshes the token (check for instagram:refresh) or create a calendar reminder — the addon is archived and will not warn you when it lapses.

Multi-site. Statamic multisite + a single Instagram account is fine (share the cached feed). Two separate accounts is not supported out of the box; you'd need to override the config per-site, which fights the single-token storage. Don't fight it — one account, one feed.

Gotchas and Tips

The API is gone. Instagram Basic Display API was shut down by Meta on 4 December 2024; the replacement is the Instagram API with Instagram Login (Graph API). Any token you generate today won't work, and this package has been archived since June 2023 with no fix coming. Treat this as a "how do I evaluate/replace it" exercise, not a greenfield install.

Expired tokens fail silently. The most common symptom is "the feed just stopped updating" — not an exception. When debugging, php artisan cache:clear first, then look at storage/logs/laravel.log for the addon's HTTP errors. If the log is empty, the addon may be swallowing 400s from Meta; wrap the tag in a try/catch or temporarily disable caching to surface the response.

Caching hides outages for days. A stale cache will happily serve old URLs that have already expired at the CDN. If images break but HTML looks right, that's a cache problem, not a template problem. Keep the TTL under 24h and add a manual invalidation step to your deploy.

Don't persist media_url. These are signed CDN URLs with a limited lifetime. Copying them into an asset field, a Markdown body, or a CSV export gives you a page full of broken images in a few weeks. Always render through the tag.

Escape caption. It can be null, contains emoji, line breaks, and — from a public account — arbitrary user text. {{ caption }} in Antlers is escaped by default; don't reach for |raw to "fix" the line breaks. Use CSS white-space: pre-line.

Composer constraints. Last release mid-2023 means the composer.json almost certainly caps at Laravel 9/10. On Laravel 11 you'll hit a dependency resolution wall; --ignore-platform-reqs is a trap here. Fork it or vendor it.

OAuth redirect must match byte-for-byte. In the Meta dashboard, https://yoursite.test/instagram/callback and https://yoursite.test/instagram/callback/ are different URIs. This bites everyone during local setup, especially with Herd/Valet .test domains over plain HTTP — Meta requires HTTPS for anything beyond a test user.

Extension points if you're maintaining a fork. The cleanest migration path is to keep the tag name and swap the implementation behind it: replace the API client with Graph API calls (/me/media?fields=id,caption,media_type,media_url,permalink,thumbnail_url,timestamp), keep the returned array shape identical, and every template keeps working. That's a ~100-line change and far cheaper than rewriting your markup.

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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels