Consultar CNPJ no Google Sheets, assim como CEP ou placa, é o tipo de tarefa que todo time operacional acaba fazendo na mão: abre o site da Receita, copia a razão social, cola na célula, repete 300 vezes. Com o Google Apps Script e a APIBrasil, isso vira uma fórmula. Você digita =CONSULTA_CNPJ(B2) e a linha se preenche com razão social, situação cadastral, município e CNAE.
O script inteiro cabe em um arquivo, não precisa de servidor e usa só recursos nativos do Sheets: UrlFetchApp para chamar a API, PropertiesService para guardar o token fora da planilha e CacheService para não pagar duas vezes pela mesma consulta.
A seguir, você cria o projeto, grava o token com segurança, escreve as três funções personalizadas (CEP, CNPJ e placa) e termina com cache, cotas e tratamento de erros para a planilha aguentar uso real.
Quando a planilha é a melhor ferramenta
Nem toda integração merece um sistema. Se a demanda é enriquecer uma lista de clientes uma vez por semana, validar os fornecedores de uma licitação ou conferir os veículos de uma frota pequena, a planilha já é o lugar onde o trabalho acontece. Levar a consulta para dentro dela elimina a troca de ferramenta e a cópia manual, que é onde os erros aparecem.
A planilha também é o formato natural de relatório operacional. Times de atendimento, por exemplo, montam um relatório de atendimento cruzando dados do CRM com informações cadastrais do cliente; ter o CNPJ resolvido na própria planilha evita exportar, processar e importar de volta.
O limite aparece quando o volume cresce. Milhares de consultas por dia, necessidade de rodar sem ninguém com a planilha aberta ou integração com outros sistemas pedem um serviço próprio, como o descrito em consultar CNPJ com a API da APIBrasil em Python. Até lá, o Apps Script resolve com muito menos esforço.
Criando o script e guardando o token
Com a planilha aberta, vá em Extensões, Apps Script. O editor abre com um arquivo Código.gs vazio; é nele que as funções abaixo entram. Antes de escrever código, guarde o token: no menu lateral do editor, abra Configurações do projeto, role até Propriedades do script e adicione uma propriedade chamada APIBRASIL_TOKEN com o Bearer Token gerado no painel da APIBrasil. Se ainda não tem um, o guia de primeiros passos com Bearer Token e homologação mostra o caminho.
Guardar o token nas propriedades, e não em uma célula ou no código, tem dois efeitos: ele não aparece para quem só lê a planilha e não vai junto quando alguém copia o script. A função base, usada por todas as outras, lê essa propriedade e trata o padrão de resposta da APIBrasil, em que o erro pode chegar com HTTP 200:
const BASE_URL = "https://gateway.apibrasil.io/api/v2";
/** Chamada genérica à APIBrasil. Lança erro com a mensagem devolvida pela API. */
function chamarApiBrasil_(caminho, corpo) {
const token = PropertiesService.getScriptProperties().getProperty("APIBRASIL_TOKEN");
if (!token) throw new Error("Defina APIBRASIL_TOKEN em Configurações do projeto > Propriedades do script");
const resposta = UrlFetchApp.fetch(BASE_URL + caminho, {
method: "post",
contentType: "application/json",
headers: { Authorization: "Bearer " + token },
payload: JSON.stringify(corpo),
muteHttpExceptions: true, // 4xx/5xx não viram exceção; tratamos abaixo
});
const codigo = resposta.getResponseCode();
let json = {};
try { json = JSON.parse(resposta.getContentText()); } catch (e) {}
// A API pode responder 200 com erro no corpo: sempre confira "error"
if (codigo >= 400 || json.error) {
throw new Error(json.message || ("HTTP " + codigo));
}
return json; // { error: false, message, data, balance, tax, ... }
}
/** Guarda o resultado por 6 horas (máximo do CacheService) para não repetir consultas cobradas. */
function comCache_(chave, fn) {
const cache = CacheService.getScriptCache();
const salvo = cache.get(chave);
if (salvo) return JSON.parse(salvo);
const valor = fn();
cache.put(chave, JSON.stringify(valor), 21600);
return valor;
}
O sufixo de sublinhado nos nomes (chamarApiBrasil_) é uma convenção do Apps Script: funções terminadas em _ não aparecem como fórmula na planilha, o que evita que alguém chame a função base direto de uma célula.
Função =CONSULTA_CEP()
A consulta de CEP usa o endpoint POST /consulta/cep/credits com tipo igual a cep. Na resposta, os dados ficam em data.cep: logradouro e estado são strings, enquanto cidade e bairro são objetos com campos próprios (a cidade traz também o código IBGE). A função devolve uma linha com cinco colunas, que o Sheets espalha automaticamente para a direita da célula onde a fórmula foi digitada.
/**
* Consulta um CEP na APIBrasil e devolve logradouro, bairro, cidade, UF e código IBGE.
* @param {string} cep CEP com ou sem hífen (ex.: "30130-010").
* @param {boolean} [homolog] true para testar sem consumir créditos.
* @return {string[][]} Uma linha com 5 colunas.
* @customfunction
*/
function CONSULTA_CEP(cep, homolog) {
const limpo = String(cep).replace(/\D/g, "");
if (limpo.length !== 8) return "CEP inválido";
return comCache_("cep:" + limpo + (homolog ? ":h" : ""), function () {
const r = chamarApiBrasil_("/consulta/cep/credits", { tipo: "cep", cep: limpo, homolog: homolog === true });
const d = r.data.cep; // confira o nome exato dos campos na documentação
return [[
d.logradouro || "",
(d.bairro && d.bairro.bairro) || "",
(d.cidade && d.cidade.cidade) || "",
d.estado || "",
(d.cidade && d.cidade.cidade_ibge) || "",
]];
});
}
O comentário com @customfunction é o que faz a fórmula aparecer no autocompletar da planilha, com a descrição dos parâmetros. Para testar sem gastar crédito, use =CONSULTA_CEP(A2; VERDADEIRO): o segundo argumento manda homolog como true e a API responde de uma base fixa. Em uma planilha com configuração regional dos Estados Unidos, o separador de argumentos é vírgula em vez de ponto e vírgula.

Consultar CNPJ no Google Sheets com =CONSULTA_CNPJ()
Aqui está o coração da planilha. O endpoint é POST /dados/cnpj/credits com tipo igual a cnpj, e a resposta traz o cadastro em data.dados: situação cadastral, nome fantasia, CNAE fiscal, endereço em campos soltos e município como objeto. Razão social, porte e capital social ficam no objeto empresa, e a opção pelo Simples ou MEI no objeto simples. Como a estrutura pode mudar entre versões, o código abaixo lê cada campo de forma defensiva.
Um detalhe que economiza dinheiro: validar os dígitos verificadores antes de chamar a API. Um CNPJ digitado errado é uma consulta cobrada que volta vazia. O algoritmo é curto e está explicado em detalhes no guia para validar CPF e CNPJ em JavaScript, PHP e Python; a versão abaixo cobre o CNPJ numérico.
/**
* Consulta um CNPJ na APIBrasil. Sem "campo", devolve uma linha com razão social,
* nome fantasia, situação, município, UF e CNAE principal.
* @param {string} cnpj CNPJ com ou sem máscara.
* @param {string} [campo] Um campo só: razao_social, nome_fantasia, situacao, municipio, uf, cnae, porte ou capital_social.
* @param {boolean} [homolog] true para testar sem consumir créditos.
* @return {string|string[][]}
* @customfunction
*/
function CONSULTA_CNPJ(cnpj, campo, homolog) {
const limpo = String(cnpj).replace(/\D/g, "");
if (!validarCnpj_(limpo)) return "CNPJ inválido";
const resumo = comCache_("cnpj:" + limpo + (homolog ? ":h" : ""), function () {
const r = chamarApiBrasil_("/dados/cnpj/credits", { tipo: "cnpj", cnpj: limpo, homolog: homolog === true });
const d = r.data.dados || r.data.cnpj || {}; // confira o caminho exato na documentação
const empresa = d.empresa || {};
return {
razao_social: empresa.razao_social || "",
nome_fantasia: d.nome_fantasia || "",
situacao: d.situacao_cadastral || "",
municipio: (d.municipio && d.municipio.descricao) || "",
uf: d.uf || "",
cnae: d.cnae_fiscal || "",
porte: empresa.porte_empresa || "",
capital_social: empresa.capital_social || "",
};
});
if (campo) {
const valor = resumo[String(campo).toLowerCase()];
return valor === undefined ? "campo desconhecido" : valor;
}
return [[resumo.razao_social, resumo.nome_fantasia, resumo.situacao, resumo.municipio, resumo.uf, resumo.cnae]];
}
/** Valida os dígitos verificadores de um CNPJ numérico com 14 dígitos. */
function validarCnpj_(cnpj) {
if (!/^\d{14}$/.test(cnpj) || /^(\d)\1{13}$/.test(cnpj)) return false;
const calc = function (base, pesos) {
let soma = 0;
for (let i = 0; i < base.length; i++) soma += Number(base[i]) * pesos[i];
const resto = soma % 11;
return resto < 2 ? 0 : 11 - resto;
};
const d1 = calc(cnpj.slice(0, 12), [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
const d2 = calc(cnpj.slice(0, 12) + d1, [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
return cnpj.slice(12) === String(d1) + String(d2);
}
O parâmetro opcional campo deixa a fórmula flexível: =CONSULTA_CNPJ(B2; “situacao”) devolve só a situação cadastral, útil para uma coluna de filtro, enquanto =CONSULTA_CNPJ(B2) preenche seis colunas de uma vez. Como as duas chamadas usam a mesma chave de cache, a segunda não gera nova cobrança.
Função =CONSULTA_PLACA()
Para veículos, a APIBrasil oferece várias consultas no mesmo endpoint, POST /consulta/veiculos/credits, diferenciadas pelo campo tipo. A versão abaixo usa agregados-basica, que devolve fabricante, modelo, anos de fabricação e modelo, cor, combustível e UF de jurisdição. Para valor de mercado, o tipo fipe-chassi retorna uma lista resultados com marca, modelo, código FIPE e valor; confira os nomes de campo na página de cada consulta.
/**
* Consulta uma placa (padrão antigo ou Mercosul) na APIBrasil e devolve
* fabricante, modelo, ano modelo, cor e UF.
* @param {string} placa Placa, ex.: "ABC1D23" ou "ABC-1234".
* @param {boolean} [homolog] true para testar sem consumir créditos.
* @return {string[][]} Uma linha com 5 colunas.
* @customfunction
*/
function CONSULTA_PLACA(placa, homolog) {
const limpa = String(placa).toUpperCase().replace(/[^A-Z0-9]/g, "");
if (!/^[A-Z]{3}\d[A-Z0-9]\d{2}$/.test(limpa)) return "Placa inválida";
return comCache_("placa:" + limpa + (homolog ? ":h" : ""), function () {
const r = chamarApiBrasil_("/consulta/veiculos/credits", { tipo: "agregados-basica", placa: limpa, homolog: homolog === true });
const d = r.data || {}; // nomes dos campos conforme a documentação da consulta
return [[d.fabricante || "", d.modelo || "", d.ano_modelo || "", d.cor || "", d.uf_jurisdicao || ""]];
});
}
A expressão regular aceita os dois formatos de placa em uso no Brasil e rejeita o resto antes de gastar crédito. Se a sua frota tem placas de outros países, relaxe a validação e deixe a API responder.
Cache, cotas e erros
Funções personalizadas são recalculadas quando os argumentos mudam e podem ser reexecutadas quando a planilha é reaberta. Sem cache, isso significa pagar de novo pela mesma consulta. O CacheService guarda o resultado por até seis horas; depois disso, a próxima recalculação chama a API novamente. Para dados que não mudam (o CEP de um endereço, a razão social de um fornecedor), copie as colunas e cole como valores assim que terminar, congelando o resultado.
O Apps Script também impõe cotas: cada função personalizada tem tempo máximo de execução, e há um limite diário de chamadas UrlFetchApp por conta. Os números atuais estão na página de cotas do Google; o que importa na prática é não arrastar uma fórmula por mil linhas de uma vez. Para lotes grandes, um menu que processa a seleção e grava valores direto é mais previsível:
function onOpen() {
SpreadsheetApp.getUi()
.createMenu("APIBrasil")
.addItem("Consultar CNPJs da seleção", "consultarCnpjsSelecionados")
.addToUi();
}
/** Lê a coluna selecionada (CNPJs) e grava o resultado nas 6 colunas à direita. */
function consultarCnpjsSelecionados() {
const intervalo = SpreadsheetApp.getActiveRange();
const linhas = intervalo.getValues();
const saida = linhas.map(function (linha) {
try {
const r = CONSULTA_CNPJ(linha[0]);
return Array.isArray(r) ? r[0] : [r, "", "", "", "", ""];
} catch (e) {
return ["ERRO: " + e.message, "", "", "", "", ""]; // saldo, token, CNPJ inexistente...
}
});
intervalo.offset(0, 1, linhas.length, 6).setValues(saida);
}
Na fórmula, um erro da API aparece como #ERROR! com a mensagem ao passar o mouse; no menu, ele vai para a célula como texto, o que facilita filtrar o que falhou e rodar de novo só essas linhas. Em qualquer dos dois caminhos, três erros são os mais comuns: token ausente ou inválido (confira a propriedade do script), saldo insuficiente (HTTP 402, recarregue no painel) e documento inexistente (a API responde error igual a true com a mensagem).
Por fim, trate o acesso à planilha como acesso ao token: quem pode editar o script consegue ler as propriedades. Em planilhas compartilhadas com muita gente, mantenha o script em uma cópia restrita e distribua apenas os valores, ou publique as funções como biblioteca com o token na biblioteca.
Perguntas frequentes
A função recalcula e cobra de novo toda vez que abro a planilha?
Com o cache de seis horas, reaberturas no mesmo período não geram nova chamada. Depois disso, uma recalculação consulta a API outra vez. Para dados estáveis, copie e cole como valores depois da consulta; a fórmula cumpriu o papel dela.
O token fica visível para quem tem acesso à planilha?
Quem apenas visualiza ou edita células não vê as propriedades do script. Quem tem permissão de editar o projeto Apps Script consegue abrir as configurações e ler o token. Restrinja a edição do script e revogue o token no painel se suspeitar de vazamento.
Por que a célula fica em “Carregando…” ou mostra #ERROR!?
“Carregando…” por mais de alguns segundos costuma indicar muitas fórmulas disparadas ao mesmo tempo ou a API demorando; aguarde ou reduza o lote. #ERROR! traz a mensagem do erro ao passar o mouse: token ausente, saldo insuficiente ou documento inválido são os casos típicos.
Dá para fazer o mesmo no Excel?
Não com este script, que é exclusivo do Google Sheets. No Excel, o caminho equivalente é Office Scripts ou Power Query chamando os mesmos endpoints com o mesmo header Authorization. A lógica de validação, cache e tratamento de error é a mesma.
Como consultar centenas de CNPJs de uma vez sem travar a planilha?
Para consultar CNPJ no Google Sheets em lote, use o menu APIBrasil em vez de arrastar a fórmula: ela processa a seleção em sequência, grava valores fixos e registra erros por linha. Para milhares de registros recorrentes, migre para um script fora da planilha, com fila e controle de saldo.
Próximos passos
Com as três funções no projeto, a planilha passa a consultar CNPJ, CEP e placa com a mesma naturalidade de um PROCV. Comece com homolog ativo para validar os mapeamentos, troque para consultas reais em um lote pequeno e acompanhe o campo balance nas respostas. Quando o volume justificar, o mesmo token e os mesmos endpoints servem para a versão em código, sem reescrever a lógica.
![]()









