Cotações da B3 em Google Sheets com IMPORTDATA: tutorial passo a passo
Imagine abrir sua planilha de carteira de manhã e ver o preço de fechamento dos últimos 30 papéis já preenchido, sem copiar e colar de site de banco, sem add-on pago, sem fórmula matricial obscura. É o que IMPORTDATA b3 entrega quando combinado com uma API REST que devolve CSV. Este tutorial mostra como montar essa planilha em cinco minutos usando a fórmula nativa do Google Sheets e a API da bolsai, e em seguida quando vale migrar para Apps Script.
O objetivo: 30 tickers atualizados sem copiar e colar
Cenário concreto: uma planilha com a coluna A listando seus papéis (PETR4, VALE3, ITSA4, MGLU3, HGLG11…) precisa mostrar na coluna B o preço de fechamento mais recente e na coluna C a variação diária. Tudo no Google Sheets, sem instalar add-on, sem servidor próprio e respeitando o limite gratuito de uma API.
Há duas abordagens viáveis. A primeira usa a função nativa IMPORTDATA, que importa um arquivo CSV remoto e distribui os campos em células adjacentes. A segunda usa Apps Script com UrlFetchApp e oferece controle fino sobre quando atualizar e como organizar os dados. Comece pela primeira; quando a planilha crescer, migre. Para a comparação mais ampla entre GOOGLEFINANCE e a abordagem via API, veja o guia anterior sobre Google Sheets com cotações da B3 via Apps Script, que detalha por que a função nativa do Google falha em FIIs e em indicadores fundamentalistas.
Pré-requisito: API key gratuita da bolsai
A bolsai expõe uma API REST com cotações da B3, 27 indicadores fundamentalistas, dividendos históricos e FIIs. Todos os endpoints aceitam autenticação via query param api_key, o que é decisivo para o IMPORTDATA: a função do Google Sheets não envia cabeçalhos HTTP personalizados, então autenticação por header (X-API-Key ou Bearer) fica fora de questão. Com a chave na URL, qualquer endpoint que suporte format=csv vira fonte de dados para a planilha.
- Acesse usebolsai.com e crie a conta gratuita com login Google. O processo leva menos de 30 segundos.
- No painel, copie a API key pessoal. Ela começa com um prefixo do tipo
sk_live_…e é a única credencial necessária para o tutorial. - Guarde a chave em local seguro. Quem tiver a chave consegue consumir o seu free tier de 200 requisições por dia; revogue e gere uma nova a qualquer momento se desconfiar de vazamento.
O plano gratuito libera 200 requisições por dia, mais do que suficiente para uma planilha pessoal de carteira que atualiza uma vez ao dia ou sob demanda. O guia completo do free tier de 200 req/dia detalha o que cabe nesse limite sem precisar migrar para plano pago.
Opção 1: IMPORTDATA puro, sem código
A fórmula IMPORTDATA aceita uma URL HTTPS que devolva CSV ou TSV. A API da bolsai entrega CSV quando o parâmetro format=csv é incluído. Combinando os dois, qualquer endpoint vira uma fonte de dados para a planilha. O exemplo mínimo, para preencher uma cotação em uma única célula:
=IMPORTDATA("https://api.usebolsai.com/api/v1/stocks/PETR4/quote?api_key=SUA_CHAVE&format=csv")
Substitua SUA_CHAVE pela API key copiada no passo anterior. Ao confirmar a fórmula, o Google Sheets faz a requisição, recebe o CSV e distribui o cabeçalho na primeira linha e os valores na segunda. O resultado ocupa nove células: ticker, trade_date, open, high, low, close, volume, traded_amount, num_trades.
Para fazer o preço aparecer numa única célula sem distribuir o CSV inteiro, encapsule a chamada em INDEX e pegue só a coluna close. Se a fórmula estiver na célula B2 e o ticker no A2, a linha fica assim:
=INDEX(
IMPORTDATA("https://api.usebolsai.com/api/v1/stocks/" & A2 & "/quote?api_key=SUA_CHAVE&format=csv"),
2, 6
)
A concatenação com A2 deixa o ticker dinâmico: arrastando a fórmula para baixo, cada linha consulta o papel correspondente. O par 2, 6 diz ao INDEX para retornar a segunda linha (valores) e a sexta coluna (close). Para estatísticas mais ricas como variação diária e máxima de 52 semanas, troque o endpoint para /stocks/{ticker}/stats?format=csv; ele devolve change_percent, high_52w, low_52w e o YTD em colunas separadas.
Endpoints úteis com format=csv
A maioria dos endpoints da bolsai suporta format=csv, o que cobre quase todos os usos de planilha pessoal. A tabela abaixo lista os mais relevantes e o que cada um entrega quando consumido via IMPORTDATA.
| Endpoint | Para que serve | Campos chave |
|---|---|---|
/stocks/{ticker}/quote |
Cotação do último pregão | close, volume |
/stocks/{ticker}/stats |
Variação diária, 52w, YTD | change_percent, high_52w |
/stocks/{ticker}/history |
Série temporal de preços | trade_date, close |
/fundamentals/{ticker} |
P/L, P/VP, ROE, dívida líquida | pl, pvp, roe |
/dividends/{ticker} |
Histórico de proventos | ex_date, amount |
/fiis/{ticker}/distributions |
Distribuições mensais de FII | amount, yield_on_price |
/screener |
Filtrar ações por critérios | todas colunas filtradas |
O endpoint /screener aceita parâmetros como dividend_yield_gt, pl_lt, roe_gt, sort e order, exatamente como descrito no guia de construção de screener em Python. Consumido via IMPORTDATA com format=csv, ele entrega uma lista pronta de candidatos direto na planilha, ideal para uma aba de prospecção. Detalhes sobre cada indicador estão em como são calculados P/L, P/VP, ROE e EV/EBITDA.
Documentação completa: a /docs lista todos os endpoints com suporte a format=csv, parâmetros aceitos, exemplos curl e os campos retornados em cada CSV.
Armadilha 1: o cache do IMPORTDATA
O Google Sheets mantém um cache interno do resultado de IMPORTDATA com TTL aproximado de uma hora. Editar a célula, recarregar a planilha ou apertar F5 não força um novo download, o que é frustrante quando se quer atualização sob demanda. A solução padrão é incluir um query param dummy ligado a uma célula auxiliar com NOW() ou um número incrementado manualmente.
# Célula Z1: =NOW() formatada como número
# Célula B2: cotação atualizada toda vez que Z1 muda
=INDEX(
IMPORTDATA("https://api.usebolsai.com/api/v1/stocks/" & A2 &
"/quote?api_key=SUA_CHAVE&format=csv&t=" & INT(Z$1*24)),
2, 6
)
O parâmetro t não é interpretado pela API e é ignorado, mas como faz parte da URL, o cache do Google enxerga URLs distintas e refaz o download. Multiplicar NOW() por 24 e arredondar com INT() gera um valor que muda a cada hora, alinhando o refresh com o TTL natural do cache. Se quiser atualização sob demanda, troque Z$1 por uma célula numérica e incremente manualmente.
Armadilha 2: segurança da API key
A chave na URL fica visível para qualquer pessoa que abra a planilha e clique na célula. Para uso pessoal isso é aceitável. Para planilhas compartilhadas com sócios, contadores ou outros usuários, o risco é real: a chave pode ser copiada, gravada em screenshots ou vazada por engano. Três cuidados resolvem o problema na ordem decrescente de esforço.
- Não compartilhe a planilha em modo de edição. No Google Sheets, acesso por link público com permissão de leitor mostra os dados renderizados mas oculta a fórmula da célula para visitantes não logados. Editores e comentaristas, porém, continuam vendo a fórmula. Use leitor sempre que possível.
- Mantenha a chave numa célula oculta. Coloque a chave em uma aba separada chamada
config, oculte a aba e referencie comconfig!A1na concatenação da URL. O ganho é cosmético, não criptográfico: editores continuam vendo, mas reduz a chance de vazamento por screenshot da aba principal. - Migre para Apps Script com
PropertiesService. A chave fica armazenada no projeto de script da planilha, não no documento, e nenhum visitante consegue lê-la. Esta é a solução robusta para qualquer planilha compartilhada com mais de uma pessoa, e está detalhada na próxima seção.
Se desconfiar de vazamento, revogue a chave atual em /dashboard e gere uma nova. As requisições com a chave antiga passam a falhar imediatamente; a planilha exibe #ERROR nas células dependentes até substituir o valor na fórmula ou no PropertiesService.
Opção 2: Apps Script com controle total
Quando a planilha cresce além de uma dezena de papéis, ou quando ela é compartilhada com outras pessoas, faz sentido migrar para Apps Script. As três vantagens centrais são guardar a chave fora das células (PropertiesService), controlar exatamente quando atualizar (botão de menu ou trigger horário) e escrever várias colunas de uma vez. O snippet abaixo lê uma lista de tickers em A2:A, chama o endpoint /stocks/{ticker}/stats em JSON e preenche preço, variação diária e máxima de 52 semanas.
/**
* Atualiza preço, variação diária e máxima de 52 semanas
* para cada ticker listado na coluna A (a partir da linha 2).
* Escreve em B (preço), C (variação %), D (52w high).
*/
function atualizarCarteira() {
const sheet = SpreadsheetApp.getActiveSheet();
const ultimaLinha = sheet.getLastRow();
if (ultimaLinha < 2) return;
const apiKey = PropertiesService.getScriptProperties()
.getProperty('BOLSAI_API_KEY');
if (!apiKey) {
throw new Error('Configure BOLSAI_API_KEY em Propriedades do script');
}
const tickers = sheet.getRange(2, 1, ultimaLinha - 1, 1)
.getValues()
.map(r => r[0])
.filter(t => t);
const resultados = tickers.map(ticker => {
const url = `https://api.usebolsai.com/api/v1/stocks/${ticker}/stats`;
const resp = UrlFetchApp.fetch(url, {
headers: { 'X-API-Key': apiKey },
muteHttpExceptions: true
});
if (resp.getResponseCode() !== 200) return ['#ERR', '#ERR', '#ERR'];
const d = JSON.parse(resp.getContentText());
return [
d.close,
d.change_percent / 100, // formato decimal para % no Sheets
d.high_52w
];
});
sheet.getRange(2, 2, resultados.length, 3).setValues(resultados);
sheet.getRange(2, 3, resultados.length, 1)
.setNumberFormat('0.00%');
}
/** Adiciona menu personalizado quando a planilha abre. */
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('bolsai')
.addItem('Atualizar carteira', 'atualizarCarteira')
.addToUi();
}
Cole o código em Extensões → Apps Script, salve, configure a chave em Configurações do projeto → Propriedades do script → BOLSAI_API_KEY e execute uma vez para autorizar o escopo script.external_request. Ao reabrir a planilha, surge um menu "bolsai" com a opção de atualizar tudo de uma vez. Note que aqui a chamada usa o header X-API-Key em vez do query param, pois com UrlFetchApp não há restrição de cabeçalhos.
Quando preferir IMPORTDATA vs Apps Script
Os dois caminhos coexistem na mesma planilha sem conflito. A decisão depende do tamanho da planilha e de quem vai usá-la. A tabela abaixo resume os tradeoffs em quatro dimensões práticas.
| Critério | IMPORTDATA | Apps Script |
|---|---|---|
| Tempo de setup | 2 minutos | 10 minutos |
| Segurança da chave | Visível na fórmula | Em PropertiesService |
| Quando atualiza | Cache de ~1h não configurável | Botão de menu, trigger ou manual |
| Múltiplas colunas por chamada | Via INDEX, uma por vez |
Várias colunas em uma só chamada |
| Volume típico de requisições/dia | Igual ao número de tickers | Controlado pelo trigger |
Para acompanhamento pessoal de carteira com 10 a 50 papéis e atualização diária, IMPORTDATA resolve. Para planilhas compartilhadas, planilhas com mais de 100 papéis ou casos que exigem refresh mid-day controlado por trigger, Apps Script é o caminho. O guia dedicado a Apps Script traz funções personalizadas reutilizáveis para indicadores e dividendos.
Template sugerido: carteira de 30 papéis
Uma estrutura que funciona bem na prática usa cinco colunas e duas abas. Na aba config, mantenha apenas a API key em A1 (oculte a aba antes de compartilhar). Na aba carteira, monte as colunas conforme a tabela abaixo. O cabeçalho da linha 1 fica fixo; as fórmulas começam na linha 2 e podem ser arrastadas para 30 ou 50 papéis.
| Coluna | Cabeçalho | Conteúdo |
|---|---|---|
| A | Ticker | Digitado manualmente (PETR4, VALE3, ITSA4…) |
| B | Quantidade | Digitada manualmente |
| C | Preço médio | Digitado manualmente |
| D | Preço atual | =INDEX(IMPORTDATA("…/stocks/" & A2 & "/quote?api_key=" & config!A$1 & "&format=csv"), 2, 6) |
| E | Variação dia | =INDEX(IMPORTDATA("…/stocks/" & A2 & "/stats?api_key=" & config!A$1 & "&format=csv"), 2, 5)/100 |
| F | Posição (R$) | =B2*D2 |
| G | Lucro/Prejuízo | =(D2-C2)*B2 |
| H | Rentabilidade % | =(D2/C2)-1 formatada como porcentagem |
Linha de totalizadores no rodapé com =SUM(F:F) para patrimônio total e =SUM(G:G) para resultado acumulado. Para enriquecer com indicadores fundamentalistas e dividendos sem complicar a planilha, adicione abas separadas com endpoints /fundamentals/{ticker} e /dividends/{ticker} também via IMPORTDATA. O guia do histórico de dividendos da bolsa brasileira mostra como interpretar os campos retornados.
Quer mais automação? Combine essa planilha com o ChatGPT conectado à bolsa brasileira via GPT Actions ou use o MCP da bolsai com Claude para gerar análises a partir dos mesmos endpoints que alimentam a planilha.
Perguntas frequentes
IMPORTDATA atualiza em tempo real?
Não. O Google Sheets mantém um cache interno do IMPORTDATA com TTL aproximado de uma hora. Recarregar a página ou editar a fórmula não força recálculo imediato. Para refresh sob demanda, troque uma parte aleatória da URL com um query param dummy ligado a NOW() ou utilize um trigger Apps Script. A API da bolsai entrega o fechamento oficial do dia após o pregão; cotação intradia em tempo real está fora do escopo dos endpoints públicos.
É seguro colocar a API key na URL do IMPORTDATA?
Tecnicamente funciona, mas quem tem acesso à planilha consegue ler a fórmula da célula e copiar a chave. Para planilhas pessoais não compartilhadas o risco é baixo. Para planilhas compartilhadas com outras pessoas, use Apps Script com PropertiesService (a chave fica em uma propriedade do projeto que não vaza para a célula). Se a chave for exposta acidentalmente, basta revogar e gerar uma nova em /dashboard.
Quantas requisições uma planilha pessoal consome?
Uma planilha com 30 papéis chamando /stocks/{ticker}/quote uma vez ao dia consome 30 requisições. Mesmo abrindo a planilha várias vezes, o cache do IMPORTDATA evita chamadas redundantes dentro da janela de 1 hora. O plano gratuito de 200 req/dia da bolsai cobre folgadamente cenários de acompanhamento pessoal com dezenas de ativos.
Quais endpoints da bolsai suportam format=csv?
A maioria. Funcionam com format=csv os endpoints de cotação (/stocks/{ticker}/quote), estatísticas (/stocks/{ticker}/stats), histórico (/stocks/{ticker}/history), fundamentalistas (/fundamentals/{ticker} e /history), dividendos (/dividends/{ticker}), FIIs (/fiis/, /{ticker}, /history, /distributions) e screener (/screener). A documentação completa lista o suporte por endpoint em /docs.
Qual a diferença entre IMPORTDATA e Apps Script para esse caso?
IMPORTDATA é declarativo e cabe em uma única célula, mas o cache de uma hora não é configurável e a chave fica visível na fórmula. Apps Script com UrlFetchApp permite controlar exatamente quando atualizar (via menu, botão ou trigger horário), guardar a chave em PropertiesService e escrever várias colunas a partir de uma lista de tickers. Para começar sem código, use IMPORTDATA; quando a planilha crescer, migre para Apps Script.
Leia também
- Google Sheets com cotações da B3 via Apps Script: o caminho avançado com funções personalizadas
- Excel com cotações de ações via Power Query: equivalente para quem usa Microsoft 365
- API gratuita para ações brasileiras: 200 req/dia: o que cabe no free tier sem migrar para Pro
- Como construir um screener de ações em Python: o endpoint
/screeneralém da planilha - Séries macro do BCB: Selic, IPCA, CDI e IGP-M: complemento para planilhas de carteira que comparam com benchmarks
- API de dados da B3: alternativas e como escolher: panorama do mercado de APIs
Disclaimer
O conteúdo deste artigo tem caráter informativo e educacional. Não constitui recomendação de compra ou venda. Os exemplos de fórmula e código são insumos técnicos 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-05-11 e podem variar após novos pregões e avisos de proventos. A API da bolsai entrega dados de fechamento oficiais da B3 e da CVM; cotação intradia em tempo real está fora do escopo dos endpoints públicos.
por bolsai • 11 de maio de 2026 • 11 min de leitura
Comece agora
Em cinco minutos sua planilha de carteira deixa de depender de copiar e colar de site de banco. IMPORTDATA com format=csv resolve o caso simples sem código; Apps Script com PropertiesService resolve o caso compartilhado com segurança. Os dois caminhos usam a mesma API e o mesmo plano gratuito de 200 requisições por dia.