API do Instagram: por que o login falha e a conta não aparece na lista
Configure conta profissional, Página, redirect e permissões na ordem certa para o botão "conectar Instagram" funcionar de primeira e a conta aparecer.
O botão "Conectar Instagram" do painel da Loja da Marta abre o Facebook, a dona da loja faz login e volta com uma tela de erro dizendo que a URL foi bloqueada. Na segunda tentativa, depois de alguém mexer no painel da Meta, o login passa, mas a lista de contas vem vazia. O time passa a tarde depurando o JavaScript do botão. O botão estava certo o tempo todo.
A resposta curta: a API de publicação do Instagram não trabalha com conta pessoal. Ela exige uma conta profissional (Comercial ou Criador de conteúdo) e, na variante com Login do Facebook, essa conta precisa estar ligada a uma Página do Facebook que a pessoa administra. Além disso, o endereço de retorno do login precisa estar cadastrado no app exatamente como o seu código envia, e o app precisa pedir as permissões de publicação e de Página. Falhou uma dessas quatro peças, o sintoma parece bug no botão.
Por que o erro tem cara de bug
O fluxo de login é OAuth: o seu site manda a pessoa para o diálogo da Meta com um client_id, um redirect_uri e uma lista de permissões (scope). A Meta autentica, pergunta o que a pessoa autoriza e devolve um código para o redirect_uri. O seu servidor troca o código por um token e, com ele, consulta as contas.
Cada etapa tem uma regra que falha em silêncio ou com mensagem genérica:
- Redirect fora da lista: a Meta compara o
redirect_uricom as URIs cadastradas nas configurações de Login do Facebook do app. Barra no final,www,httpem vez dehttpsou um caminho diferente bastam para o bloqueio. - Conta pessoal: o login funciona, porque a pessoa tem conta no Facebook, mas não existe conta do Instagram empresarial para devolver. A lista vem vazia, sem erro.
- Conta profissional sem Página: a API encontra a conta do Instagram pela Página. Sem o vínculo, de novo, lista vazia.
- Permissão que faltou no
scopeou que a pessoa desmarcou: o token existe, mas a chamada de Páginas devolve vazio ou a publicação devolve erro de permissão.
A Meta também oferece uma variante de login pelo próprio Instagram, com requisitos diferentes (sem a Página). Antes de seguir qualquer tutorial, confirme na documentação qual das duas variantes o seu app usa, porque as permissões e os endpoints mudam.
Como configurar na ordem certa
- Converta a conta. No app do Instagram, nas configurações de tipo de conta, mude para conta profissional. A conversão não apaga posts nem seguidores.
- Ligue a conta a uma Página. Pela Página do Facebook (ou pelo Meta Business Suite), vincule a conta do Instagram. Quem vai clicar em "Conectar" precisa ter função de administração nessa Página.
- Cadastre o redirect exato. No painel do app, em Login do Facebook, adicione a URI de retorno completa, com
https, domínio e caminho. Cadastre também a de homologação, se houver, e mantenha cada uma idêntica à do código. - Peça só as permissões necessárias. Para publicar com Login do Facebook, a documentação de publicação de conteúdo lista as exigidas; o núcleo costuma ser
instagram_basic,instagram_content_publishe as de Página, comopages_show_listepages_read_engagement. Confira a lista atual no guia oficial antes de enviar o app para revisão. - Teste em modo de desenvolvimento com pessoas do time. Enquanto o app não passa pela revisão da Meta, só contas com função no app (administrador, desenvolvedor, testador) conseguem autorizar as permissões avançadas. A cliente de fora do time vai ver erro até lá.
- Troque o código pelo token no servidor, com o segredo do app guardado no backend, e só então busque as contas.
Exemplo: o fluxo completo no servidor em Node
O código abaixo roda em Node 18 ou mais novo (tem fetch nativo). A versão da Graph API vem de variável de ambiente, porque a Meta aposenta versões com o tempo; use a que o painel do app indica, no formato vNN.0.
// meta-login.js
const crypto = require('crypto');
const APP_ID = process.env.META_APP_ID;
const APP_SECRET = process.env.META_APP_SECRET; // nunca no front-end
const VERSAO = process.env.GRAPH_VERSION; // ex.: a versão mostrada no painel
const GRAPH = 'https://graph.facebook.com/' + VERSAO;
const REDIRECT_URI = 'https://painel.lojadamarta.com.br/meta/callback';
function urlDeLogin(sessao) {
sessao.oauthState = crypto.randomBytes(16).toString('hex');
const p = new URLSearchParams({
client_id: APP_ID,
redirect_uri: REDIRECT_URI,
state: sessao.oauthState,
response_type: 'code',
scope: 'instagram_basic,instagram_content_publish,pages_show_list,pages_read_engagement'
});
return 'https://www.facebook.com/' + VERSAO + '/dialog/oauth?' + p.toString();
}
async function lerJson(resposta) {
const corpo = await resposta.json();
if (!resposta.ok || corpo.error) {
throw new Error('Graph API: ' + (corpo.error ? corpo.error.message : resposta.status));
}
return corpo;
}
async function callback(sessao, query) {
if (!query.state || query.state !== sessao.oauthState) {
throw new Error('state inválido');
}
const p = new URLSearchParams({
client_id: APP_ID,
client_secret: APP_SECRET,
redirect_uri: REDIRECT_URI, // tem de ser a mesma string do login
code: query.code
});
const token = await lerJson(await fetch(GRAPH + '/oauth/access_token?' + p.toString()));
const paginas = await lerJson(await fetch(
GRAPH + '/me/accounts?fields=name,instagram_business_account&access_token=' +
encodeURIComponent(token.access_token)
));
return paginas.data
.filter((pg) => pg.instagram_business_account)
.map((pg) => ({ pagina: pg.name, igUserId: pg.instagram_business_account.id }));
}
module.exports = { urlDeLogin, callback };
Se callback devolve um array vazio, o problema não é o código: a conta é pessoal, não está ligada à Página, ou a pessoa não administra a Página. Se paginas.data já vem vazio, faltou pages_show_list ou a pessoa desmarcou as Páginas na tela de autorização. Essa separação, sozinha, economiza a tarde que o time da Marta perdeu.
Com o igUserId em mãos, a publicação acontece em duas chamadas (criar o contêiner de mídia e publicar), e a imagem precisa estar numa URL pública que os servidores da Meta consigam baixar. Os detalhes do que entra na publicação estão em o que entra numa publicação feita pela API do Instagram.
Como diagnosticar o redirect bloqueado
Copie o redirect_uri da barra de endereço da tela de erro (ele vem codificado; decodifique) e compare com o cadastrado, caractere por caractere. Na Loja da Marta, o código enviava https://painel.lojadamarta.com.br/meta/callback/, com barra final, e o painel tinha a versão sem barra. Um caractere. Use uma constante única no código, como no exemplo, e cole exatamente ela no painel.
Repare que o mesmo redirect_uri aparece duas vezes: no diálogo e na troca do código. Se as duas strings diferem, a troca falha mesmo com o login aprovado.
Erros comuns
- Testar com a conta pessoal de quem programa. O login passa, a lista vem vazia, e o time conclui que a API está fora do ar.
- Cadastrar só o domínio, sem o caminho completo do callback. A Meta exige a URI de retorno; o login termina em "URL bloqueada".
- Pedir todas as permissões do catálogo "por garantia". A revisão do app fica mais difícil de aprovar e a tela de autorização assusta quem vai clicar.
- Trocar o código pelo token no navegador. O segredo do app vai junto para o front-end e qualquer pessoa pode se passar pelo seu app.
- Ignorar o parâmetro
state. Sem ele, um atacante consegue fazer a vítima concluir um login iniciado por outra pessoa e ligar a conta errada ao seu painel. - Abrir o app para clientes ainda em modo de desenvolvimento. Só quem tem função no app consegue autorizar; o resto vê erro e acha que o produto quebrou.
Checklist
- A conta do Instagram aparece como profissional (Comercial ou Criador) nas configurações.
- A conta está vinculada a uma Página, e quem conecta tem função de administração nela.
- O
redirect_urido código é uma constante e está cadastrado idêntico no painel, comhttps. - O mesmo
redirect_urié usado no diálogo e na troca do código. - O
scopetem só as permissões que a documentação de publicação exige. - O segredo do app está no servidor, em variável de ambiente, e não no JavaScript do navegador.
- O
stateé gerado por sessão e conferido no callback. - O app passou pela revisão da Meta antes de ir para clientes fora do time.
Para fechar o ciclo do OAuth com segurança, vale ler por que o segredo do OAuth fica no servidor e o risco de um redirect que obedece a qualquer parâmetro. Agora abra a tela de erro do seu último login: o redirect_uri que ela mostra é idêntico, caractere por caractere, ao que está cadastrado no app?
Referência: https://developers.facebook.com/docs/instagram-api/getting-started