Google Sheets com Cotações da B3 em Tempo Real via API
Quem usa google sheets cotações B3 conhece o teto invisível da função GOOGLEFINANCE: cobertura irregular de FIIs, ausência de indicadores fundamentalistas e nenhum histórico de dividendos. Este guia mostra como estender o Google Sheets com Apps Script e a API da bolsai, criando fórmulas personalizadas que consultam preço, P/L, ROE, dividend yield e dados de FII direto de qualquer célula da planilha.
Por que GOOGLEFINANCE não é suficiente para ações brasileiras
A função GOOGLEFINANCE devolve cotação e histórico básicos de ações listadas na B3, mas falha em FIIs, não expõe múltiplos como P/L e P/VP, não cobre dividendos e opera com atraso de 15 a 20 minutos no pregão. Para cotação google sheets brasil completa é preciso chamar uma API dedicada via Apps Script.
O caso mais frequente são os fundos imobiliários. Tickers como HGLG11, MXRF11 e KNRI11 retornam #N/A em muitos ambientes da função, mesmo quando prefixados com BVMF:. A documentação do próprio Google classifica o mercado brasileiro como cobertura parcial, e a atualização é intencionalmente atrasada. Para uma planilha de acompanhamento, o efeito prático é ter células vazias justamente nos papéis de renda mensal que motivaram o esforço.
A segunda lacuna é fundamentalista. GOOGLEFINANCE entrega price, volume, marketcap e pouco mais. Não existe atributo para P/L, P/VP, ROE, margem líquida, dividend yield histórico ou payout. Uma carteira montada no Google Sheets fica dependente de copiar e colar dados de sites de terceiros, processo frágil que quebra quando qualquer layout muda. O guia da API gratuita da B3 detalha os endpoints que substituem esse fluxo manual.
O que a API da bolsai adiciona ao Google Sheets
A bolsai é uma API REST que agrega dados oficiais da B3 e da CVM e entrega preços, 27 indicadores fundamentalistas, FIIs e dividendos em JSON pronto para consumir. Ao conectar essa API ao Google Sheets via Apps Script, a planilha deixa de depender de um único atributo fixo e passa a receber qualquer dado do mercado brasileiro em células comuns. A tabela abaixo resume o contraste entre a função nativa e o caminho via API.
| Dado | GOOGLEFINANCE | API bolsai via Apps Script |
|---|---|---|
| Cotação de ações (PETR4, VALE3) | Parcial, atraso de 15-20 min | Fechamento diário oficial do COTAHIST |
| Cotação de FIIs (HGLG11, MXRF11) | Falhas frequentes, retorna #N/A | Cobertura de 400+ FIIs |
| Indicadores fundamentalistas (P/L, ROE, DY) | Não disponível | 27 indicadores calculados com TTM |
| Dividendos e JCP históricos | Não disponível | Histórico completo por ticker |
| Histórico de preços longo prazo | Limitado, fórmula matricial | Séries desde 1986 via COTAHIST |
| Delay de atualização | 15-20 minutos no plano padrão | Fechamento D+0 após o pregão |
Setup inicial: API key da bolsai e Apps Script
O caminho entre abrir uma planilha nova e ter a primeira fórmula personalizada funcionando leva cerca de cinco minutos. A única dependência externa é a API key obtida no painel em usebolsai.com. O passo a passo abaixo assume um Google Sheets vazio.
- Crie uma conta em usebolsai.com, acesse
/dashboarde copie a chave pessoal. O plano gratuito libera 200 requisições por dia, suficiente para planilhas de acompanhamento com algumas dezenas de papéis. - No Google Sheets, abra o menu Extensões → Apps Script. Uma aba nova abre com um editor de código vazio. Remova o conteúdo padrão.
- Cole o código do editor de funções personalizadas mostrado adiante. Salve com
Ctrl+Sou no botão de disquete. Um clique em Executar a primeira vez pedirá autorização OAuth do Google para acessar URLs externas. - Configure a chave em Propriedades do projeto → Propriedades do script, chave
BOLSAI_API_KEY, valor igual à API key copiada. UsarPropertiesServiceevita hard-coding da chave no código da planilha compartilhada. - Volte à planilha e digite
=BOLSAI_QUOTE("PETR4")em qualquer célula. O valor aparece em segundos. Se a célula marcar#ERROR!, abra o editor em Execução → Logs para ver a mensagem; o motivo mais comum é chave ausente ou ticker inválido.
A autorização OAuth é exigida pelo Google em qualquer Apps Script que chame domínios externos. O escopo pedido é script.external_request. A aprovação é pontual e fica persistida no projeto; recarregar a planilha não reexibe o prompt.
A documentação completa da API lista todos os endpoints aceitos pelas funções abaixo, os campos retornados no JSON e os parâmetros opcionais para histórico, screener e exportação CSV.
Função customizada: =BOLSAI_QUOTE("PETR4") para cotação
A fórmula mais básica consulta o endpoint /stocks/{ticker}/quote e devolve o preço de fechamento. A implementação abaixo usa UrlFetchApp para a requisição HTTP, PropertiesService para ler a chave e CacheService para poupar chamadas repetidas. Cinco minutos de cache é suficiente porque o pregão oficial da B3 fecha em D+0 e o valor não muda durante a sessão.
/**
* Retorna o último preço de fechamento de uma ação da B3.
* @param {string} ticker Ticker da ação (ex: "PETR4").
* @return {number} Preço de fechamento.
* @customfunction
*/
function BOLSAI_QUOTE(ticker) {
if (!ticker) throw new Error("Informe o ticker");
ticker = String(ticker).toUpperCase().trim();
const cache = CacheService.getScriptCache();
const cacheKey = "quote_" + ticker;
const cached = cache.get(cacheKey);
if (cached) return Number(cached);
const key = PropertiesService.getScriptProperties().getProperty("BOLSAI_API_KEY");
if (!key) throw new Error("BOLSAI_API_KEY ausente em Propriedades do script");
const url = "https://api.usebolsai.com/api/v1/stocks/" + ticker + "/quote";
const res = UrlFetchApp.fetch(url, {
headers: { "X-API-Key": key },
muteHttpExceptions: true
});
if (res.getResponseCode() !== 200) {
throw new Error("HTTP " + res.getResponseCode() + ": " + res.getContentText());
}
const data = JSON.parse(res.getContentText());
const price = data.close;
cache.put(cacheKey, String(price), 300); // 5 minutos
return price;
}
Uso em célula: =BOLSAI_QUOTE("PETR4"), =BOLSAI_QUOTE(A2) ou arrastando a fórmula para baixo em uma coluna com a lista de tickers. Valores retornados já saem como número, então formatações de moeda em R$ no Google Sheets funcionam sem conversão extra.
Função para indicadores fundamentalistas: =BOLSAI_FUNDAMENTAL("ITUB4", "pl")
A mesma estrutura serve para qualquer endpoint. O endpoint /fundamentals/{ticker} devolve 27 campos, entre eles pl, pvp, roe, net_margin, ev_ebitda, market_cap e lpa. A função abaixo aceita dois argumentos e retorna o campo solicitado, permitindo que uma planilha cobre múltiplos indicadores do mesmo papel com fórmulas em colunas separadas. Dividend yield vive em endpoint próprio, detalhado na próxima seção.
/**
* Retorna um indicador fundamentalista de uma ação.
* @param {string} ticker Ticker da ação.
* @param {string} field Campo desejado (pl, pvp, roe, ev_ebitda, lpa, vpa, ...).
* @return {number} Valor do indicador.
* @customfunction
*/
function BOLSAI_FUNDAMENTAL(ticker, field) {
if (!ticker || !field) throw new Error("ticker e field são obrigatórios");
ticker = String(ticker).toUpperCase().trim();
field = String(field).toLowerCase().trim();
const cache = CacheService.getScriptCache();
const cacheKey = "fund_" + ticker;
let json = cache.get(cacheKey);
if (!json) {
const key = PropertiesService.getScriptProperties().getProperty("BOLSAI_API_KEY");
const url = "https://api.usebolsai.com/api/v1/fundamentals/" + ticker;
const res = UrlFetchApp.fetch(url, {
headers: { "X-API-Key": key },
muteHttpExceptions: true
});
if (res.getResponseCode() !== 200) {
throw new Error("HTTP " + res.getResponseCode());
}
json = res.getContentText();
cache.put(cacheKey, json, 21600); // 6 horas: fundamentos mudam com publicação de DFP/ITR
}
const data = JSON.parse(json);
if (!(field in data)) {
throw new Error("Campo '" + field + "' não existe. Veja /docs.");
}
return data[field];
}
Usos típicos em célula: =BOLSAI_FUNDAMENTAL("ITUB4","pl"), =BOLSAI_FUNDAMENTAL(A2,"roe"), =BOLSAI_FUNDAMENTAL(A2,"ev_ebitda"). A lista completa de campos disponíveis está detalhada em /docs. Para dividend yield usa-se o endpoint /dividends/{ticker}, que expõe o campo dividend_yield_ttm e pode ser lido por uma variação da função acima com base "https://api.usebolsai.com/api/v1/dividends/". Quem está começando e quer uma explicação mais detalhada dos múltiplos encontra o passo a passo no artigo sobre P/L em Python, que aplica a mesma metodologia que alimenta a API.
Função para FIIs: cotação e dividend yield
Os FIIs concentram a maior parte das falhas do GOOGLEFINANCE. O endpoint /fiis/{ticker} devolve cotação (close_price), P/VP, dividend yield de 12 meses (dividend_yield_ttm), valor patrimonial por cota, segmento e número de cotistas. A função abaixo extrai qualquer um desses campos, eliminando a necessidade de consultar múltiplas planilhas externas.
/**
* Retorna dados de um fundo imobiliário.
* @param {string} ticker Ticker do FII (ex: "HGLG11").
* @param {string} field Campo: close_price, pvp, dividend_yield_ttm, book_value_per_share, segment.
* @return {*} Valor do campo solicitado.
* @customfunction
*/
function BOLSAI_FII(ticker, field) {
if (!ticker) throw new Error("Informe o ticker do FII");
ticker = String(ticker).toUpperCase().trim();
field = (field || "close_price").toLowerCase().trim();
const cache = CacheService.getScriptCache();
const cacheKey = "fii_" + ticker;
let json = cache.get(cacheKey);
if (!json) {
const key = PropertiesService.getScriptProperties().getProperty("BOLSAI_API_KEY");
const url = "https://api.usebolsai.com/api/v1/fiis/" + ticker;
const res = UrlFetchApp.fetch(url, {
headers: { "X-API-Key": key },
muteHttpExceptions: true
});
if (res.getResponseCode() !== 200) {
throw new Error("HTTP " + res.getResponseCode() + " em /fiis/" + ticker);
}
json = res.getContentText();
cache.put(cacheKey, json, 3600); // 1 hora: informe mensal do FII é pouco frequente
}
const data = JSON.parse(json);
return data[field];
}
Exemplos de uso: =BOLSAI_FII("HGLG11","close_price") devolve a cotação, =BOLSAI_FII("MXRF11","dividend_yield_ttm") devolve o DY anualizado em percentual e =BOLSAI_FII("KNRI11","pvp") devolve o P/VP. A mesma fórmula arrasta por uma coluna com 50 tickers de FII sem cair em #N/A, algo que GOOGLEFINANCE raramente sustenta. Para aprofundar a análise por segmento (logística, lajes, papel, shopping, híbridos), o artigo sobre API de fundos imobiliários mostra variações avançadas de leitura.
Atualização automática com triggers
Funções personalizadas do Apps Script não recalculam a cada tick do mercado. Elas rodam quando a célula é editada, quando a planilha é aberta ou quando algum evento dispara o recálculo. Para manter a carteira atualizada durante o pregão sem intervenção manual, a combinação padrão é um trigger por tempo que sobrescreve uma célula de timestamp, forçando o Google Sheets a reexecutar todas as fórmulas que dependem dela indiretamente.
/**
* Atualiza célula de controle para forçar recálculo das fórmulas.
* Criar trigger: no editor, relógio lateral → Adicionar trigger
* → Função: forceRefresh | Fonte: Por tempo | Tipo: Timer por hora.
*/
function forceRefresh() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Carteira");
if (!sheet) return;
// Invalida caches para forçar nova chamada à API
CacheService.getScriptCache().removeAll([]);
// Escreve timestamp em uma célula auxiliar (ex: Z1)
sheet.getRange("Z1").setValue(new Date());
}
Para criar o trigger, abre-se o editor de Apps Script, clica-se no ícone de relógio na barra lateral esquerda e adiciona-se uma nova regra: origem Por tempo, tipo Timer por hora, intervalo A cada hora. Uma restrição do Apps Script é que triggers não rodam em contas gratuitas fora do horário comercial em casos raros de cota; o caminho seguro é aceitar o comportamento padrão e limitar o horário via guarda if checando new Date().getUTCHours() entre 13 e 21 UTC, janela que cobre 10h-18h em Brasília. A documentação oficial do Apps Script está em developers.google.com/apps-script.
Exemplo prático: carteira de acompanhamento
Uma planilha de acompanhamento completo nasce combinando as três funções em colunas disciplinadas. A estrutura abaixo é a que tem rendido melhor em uso real: primeira aba com tickers, quantidade e preço médio, colunas seguintes preenchidas automaticamente pelas fórmulas. Cada linha descreve uma posição.
| Coluna | Fórmula | Resultado esperado |
|---|---|---|
| A: Ticker | PETR4 (manual) |
Entrada do usuário |
| B: Quantidade | 200 (manual) |
Entrada do usuário |
| C: Preço médio | 28.50 (manual) |
Entrada do usuário |
| D: Preço atual | =BOLSAI_QUOTE(A2) |
Fechamento diário |
| E: P/L | =BOLSAI_FUNDAMENTAL(A2,"pl") |
Múltiplo TTM |
| F: Dividend Yield | =BOLSAI_FUNDAMENTAL(A2,"dividend_yield") * |
DY 12m (via /dividends) |
| G: Valor da posição | =B2*D2 |
R$ na cotação do dia |
| H: Lucro/Prejuízo | =(D2-C2)*B2 |
Resultado financeiro |
| I: Variação % | =(D2/C2)-1 |
Formatar como porcentagem |
Para a coluna F funcionar como descrita, a função BOLSAI_FUNDAMENTAL precisa de uma variação específica para dividendos: basta duplicar a função trocando o endpoint de /fundamentals/ para /dividends/, ou criar uma função BOLSAI_DIVIDEND_YIELD(ticker) dedicada que retorne data.dividend_yield_ttm. A linha de rodapé usa =SUM(G:G) para patrimônio total, =SUMPRODUCT(F:F,G:G)/SUM(G:G) para DY ponderado e =SUM(H:H) para lucro acumulado. Uma carteira de 30 papéis atualizada de hora em hora consome cerca de 90 requisições por dia com cache de 5-60 min, cabendo confortavelmente no free tier. O comparativo bolsai vs brapi traz números detalhados sobre cobertura e limites, útil antes de fixar a planilha em um fornecedor.
Perguntas frequentes
É possível usar a bolsai sem o Apps Script?
Sim. Qualquer linguagem ou ferramenta que faça requisições HTTP consome a API: Python, Node, Excel com Power Query, Notion com blocos de código, n8n, Zapier e assistentes como Claude via MCP. O Apps Script é apenas a via mais direta dentro do próprio Google Sheets porque permite escrever funções personalizadas que atuam como fórmulas de célula, sem precisar de add-on externo nem de servidor intermediário.
A API funciona com IMPORTDATA direto?
Não de forma recomendada. IMPORTDATA exige URL pública que retorne CSV e não envia cabeçalhos HTTP personalizados. A chave de API da bolsai viaja no cabeçalho X-API-Key, o que torna IMPORTDATA inadequado. O caminho estável é Apps Script com UrlFetchApp, que aceita headers arbitrários, respeita o limite de chamadas e permite cache via CacheService. Dito isso, quem insiste em usar importdata ações brasileiras sem Apps Script pode expor um endpoint proxy próprio em Cloud Functions ou similar que injete a chave no header e devolva CSV público, fluxo que funciona, mas aumenta a complexidade.
Qual o limite de chamadas no plano gratuito?
O plano gratuito libera 200 requisições por dia. Para uma planilha com 30 papéis consultando cotação e um indicador a cada hora durante o pregão, o volume cabe no limite desde que o CacheService seja utilizado. O plano Pro (R$ 49/mês) sobe o teto para 10.000 chamadas diárias, adequado para planilhas compartilhadas ou múltiplas abas de acompanhamento. Os detalhes e comparativo estão em /#pricing.
O Google Sheets atualiza em tempo real?
Funções personalizadas do Apps Script não disparam a cada tick. O recálculo ocorre quando a célula é editada, quando a planilha é reaberta ou quando um trigger programado força a atualização. O padrão que funciona bem é combinar CacheService (evita chamar a API toda vez que a célula recalcula) com um trigger horário durante o pregão que sobrescreve uma célula de timestamp, forçando as fórmulas a recalcularem. A B3 publica o COTAHIST oficial após o fechamento, então cotação intradia pura está fora do escopo da função BOLSAI_QUOTE. Detalhes sobre o pregão e o calendário oficial da bolsa estão em b3.com.br.
Leia também
- Como consultar cotação de ação em Python: mesma API, ambiente backend com
requests,httpxe retry - API gratuita da B3: guia completo em Python: mapa dos endpoints, free tier e padrões de uso
- API de fundos imobiliários com Python: cobertura de FIIs, dividendos mensais e comparação entre segmentos
Disclaimer
O conteúdo deste artigo tem caráter informativo e educacional. Não constitui recomendação de compra ou venda. Indicadores são insumos para análise e não substituem due diligence nem avaliação compatível com o perfil do investidor. Valores ilustrativos refletem a base pública disponível em 2026-04-01 e podem variar após novos ITRs, DFPs e avisos de proventos.
por bolsai • 19 de abril de 2026 • 10 min de leitura
Comece agora
Planilhas construídas em cima de google sheets cotações B3 via API ganham autonomia imediata: cobertura de FIIs que o GOOGLEFINANCE não entrega, fundamentalistas calculados com TTM e dividendos históricos, tudo dentro da mesma célula. O plano gratuito libera 200 requisições diárias, suficiente para uma carteira de 30 a 50 papéis com atualização horária.