Well-typed React component for Instagram Business Login — the Instagram API with Instagram Login business login flow.
It is the Instagram counterpart to react-es-fb-login, but the underlying
mechanics are different — see How it works.
- 💙 TypeScript first — fully typed props, params and responses
- 📦 Tiny, zero runtime dependencies
- 🔁 Full-page redirect or popup flow
- 🔒 Backend token exchange (the only safe way for Instagram)
- ⚛️ Works with React 16 → 20
- How it works
- Prerequisites
- Getting started
- Usage
- Scopes
- Props
- API reference
- Backend: exchanging the code
- TypeScript
- Examples
- Development
- Author
- License
- Links
⚠️ Important — read this before integrating.Unlike Facebook Login, Instagram Business Login has no JavaScript SDK and there is no client-side access token. The flow is pure OAuth 2.0:
- This component sends the user to
https://www.instagram.com/oauth/authorize(redirect or popup).- Instagram redirects back to your
redirectUriwith a short-lived?code=...(valid ~1 hour).- This component reads that
codeand hands it to youronSuccesscallback.- Your backend exchanges the
codefor an access token by POSTing tohttps://api.instagram.com/oauth/access_tokenwith the app'sclient_secret. The secret must never be exposed in browser code, so this step cannot happen in the package.So: the frontend's only job is to obtain the
code. Everything after that is the backend's responsibility.
Browser (this package) Your Backend
────────────────────── ─────────────
click "Login with Instagram"
│
▼
redirect to instagram.com/oauth/authorize
│ (user approves)
▼
redirect back to redirectUri?code=AUTH_CODE
│
▼
onSuccess({ code }) ───────POST code──────► POST api.instagram.com/oauth/access_token
(client_id, client_secret, code, redirect_uri)
│
▼
short-lived token ─► long-lived token (60d)
- A Meta app with the Instagram product added and Instagram Business Login set up.
- Your Instagram App ID (used as
appId/client_id). - One or more redirect URIs registered in the App Dashboard — the
redirectUriyou pass must match one of them exactly. - A backend endpoint that can exchange the authorization code for a token using your Instagram App Secret (see Backend: exchanging the code).
npm i --save react-es-ig-login
# or
yarn add react-es-ig-login
# or
pnpm add react-es-ig-loginreact is a peer dependency (^16 || ^17 || ^18 || ^19 || ^20).
By default the component does a full-page redirect. Render the same
component on your redirectUri page and it detects the redirect-back on mount
(matching on state), then fires onSuccess / onFail automatically.
import InstagramLogin from 'react-es-ig-login';
<InstagramLogin
appId="YOUR_INSTAGRAM_APP_ID"
redirectUri="https://app.example.com/auth/instagram"
scope="instagram_business_basic"
onSuccess={(res) => {
// Send res.code to your backend to exchange it for an access token.
fetch('/api/instagram/exchange', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: res.code }),
});
}}
onFail={(err) => {
console.log('Login failed:', err);
}}
/>;Set useRedirect={false} to open the auth screen in a popup instead of
navigating the whole page. The result is delivered via the callbacks without a
page reload.
The
redirectUripage must be same-origin with the page that opened the popup — the package pollspopup.locationto read the code once it returns. If your redirect page lives on a different origin, use the redirect flow.
<InstagramLogin
appId="YOUR_INSTAGRAM_APP_ID"
redirectUri="https://app.example.com/auth/instagram"
useRedirect={false}
popupParams={{ width: 500, height: 720 }}
onSuccess={(res) => console.log(res.code)}
onFail={(err) => console.log(err)}
/>Provide render to replace the default button with your own trigger:
<InstagramLogin
appId="YOUR_INSTAGRAM_APP_ID"
redirectUri="https://app.example.com/auth/instagram"
render={({ onClick }) => (
<button className="my-ig-button" onClick={onClick}>
Continue with Instagram
</button>
)}
/>Or pass children / style / className to style the built-in button.
Drive the flow manually without the component:
import { InstagramLoginClient } from 'react-es-ig-login';
// 1. Kick off login (full-page redirect)
InstagramLoginClient.redirect({
client_id: 'YOUR_INSTAGRAM_APP_ID',
redirect_uri: 'https://app.example.com/auth/instagram',
scope: 'instagram_business_basic',
state: 'instagramdirect',
});
// 2. On the redirect_uri page
if (InstagramLoginClient.isRedirected('instagramdirect')) {
const res = InstagramLoginClient.getResponse();
// res => { code, state } | { error, error_reason, error_description }
}
// Or just build the authorize URL yourself
const url = InstagramLoginClient.getAuthUrl({
client_id: 'YOUR_INSTAGRAM_APP_ID',
redirect_uri: 'https://app.example.com/auth/instagram',
});Pass a comma-separated string to scope:
| Scope | Purpose |
|---|---|
instagram_business_basic |
Basic profile + media (default) |
instagram_business_content_publish |
Publish content |
instagram_business_manage_messages |
Read / manage messages |
instagram_business_manage_comments |
Read / manage comments |
scope="instagram_business_basic,instagram_business_content_publish"| Property | Description | Type | Default |
|---|---|---|---|
appId * |
Your Instagram App ID (client_id). |
string | - |
redirectUri * |
Registered redirect URI Instagram returns to. | string | - |
scope |
Comma-separated permissions. | string | 'instagram_business_basic' |
state |
CSRF value returned unchanged. | string | 'instagramdirect' |
enableFBLogin |
Toggle "Continue with Facebook" on the auth screen. | boolean | true (Instagram default) |
forceReauth |
Force the user to re-enter credentials. | boolean | false |
useRedirect |
Full-page redirect (true) or popup (false). |
boolean | true |
autoLoad |
Start login on mount. | boolean | false |
onSuccess |
Called with { code, state }. |
function | - |
onFail |
Called with { error, error_reason?, error_description? }. |
function | - |
style |
CSS for the default button. | CSSProperties | - |
className |
Class for the default button. | string | - |
children |
Button content. | ReactNode | 'Login with Instagram' |
render |
Render a custom trigger: ({ onClick }) => ReactElement. |
function | - |
authorizeParams |
Override / extra authorize query params. | Partial<AuthorizeParams> | - |
popupParams |
Popup sizing (used when useRedirect={false}). |
{ width?, height?, name? } |
{ width: 600, height: 700 } |
* = required.
InstagramLoginClient methods:
| Method | Returns | Description |
|---|---|---|
getAuthUrl(params) |
string |
Build the instagram.com/oauth/authorize URL. |
redirect(params) |
void |
Navigate the whole window to the authorize screen. |
openPopup(params, onSuccess, onFail, popup?) |
void |
Open the authorize screen in a popup and resolve via callbacks. |
isRedirected(state?) |
boolean |
Whether the current URL is a redirect-back (optionally matching state). |
parseResponse(search) |
AuthResponse |
Parse { code, state } or { error, ... } from a query string. |
getResponse() |
AuthResponse |
Parse the auth response from the current window URL. |
Where AuthResponse = SuccessResponse | FailResponse:
type SuccessResponse = { code: string; state?: string };
type FailResponse = {
error: string; // 'access_denied' | 'popupBlocked' | 'popupClosed' | 'noWindow' | ...
error_reason?: string;
error_description?: string;
};The step this package deliberately leaves to your server:
POST https://api.instagram.com/oauth/access_token
Content-Type: application/x-www-form-urlencoded
client_id=YOUR_INSTAGRAM_APP_ID
&client_secret=YOUR_INSTAGRAM_APP_SECRET
&grant_type=authorization_code
&redirect_uri=https://app.example.com/auth/instagram
&code=AUTH_CODE_FROM_onSuccessThe response contains a short-lived access token. Exchange it for a long-lived (60-day) token:
GET https://graph.instagram.com/access_token
?grant_type=ig_exchange_token
&client_secret=YOUR_INSTAGRAM_APP_SECRET
&access_token=SHORT_LIVED_TOKENLong-lived tokens can be refreshed (once they are ≥ 24h old and unexpired) at
https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token.
All public types are exported:
import type {
InstagramLoginProps,
AuthorizeParams,
InstagramScope,
SuccessResponse,
FailResponse,
AuthResponse,
PopupParams,
} from 'react-es-ig-login';See examples/ for component, popup, custom-render and
client-only usage.
npm install # install dependencies
npm run check # lint + type-check + tests (in parallel)
npm run check:test # jest only
npm run build # emit dist/ with type declarationsankit5hukla — github.com/4nkit-5hukla