Programando bots para o Mastodon: identificando instâncias brasileiras
Hoje veremos como criar scripts que buscam as informações de identificação de uma instância, e de que forma é possível identificar se ela é brasileira – ou, no mínimo, se suas informações estão em português.
O meu script de censo do Fediverso BR é executado aproximadamente uma vez por ano. Ele percorre as dezenas de milhares (mais de 100.000, neste momento) de servidores federados, buscando identificar quais correspondem a instâncias brasileiras, e quais as tendências em relação a elas.
Eu resisto a compartilhá-lo, porque como envolve mais de 100.000 servidores, eu não quero contribuir gerar ainda mais demandas e custos aos seus admins, ao facilitar que um monte de gente rode scripts que os contatem indiscriminadamente.
Compartilhando só a lógica central
Neste final de semana eu estou rodando essa rotina novamente (a vez anterior foi em fevereiro de 2025), e o Josir Gomes voltou a me pedir pra compartilhar o script. Eu tenho certeza de que a intenção dele é boa, pois sei que ele é pesquisador sobre esse tema, e que seu interesse (assim como o de outros pesquisadores e interessados) é legítimo.

Por isso,decidi compartilhar (só) o filé mignon do meu script: as rotinas que obtém os dados sobre um servidor, e a descrição do método que uso para identificar se são brasileiros (ou lusófonos, dependendo do critério). Ao final, faço um pedido especial de responsabilidade ao usar as técnicas aqui descritas.
Importante: Para rodar os scripts abaixo, você precisa ter uma shell Bash ou compatível, com o awk e o gron (para facilitar o consumo das respostas em formato JSON), instalados em um sistema compatível com o Posix (como a maior parte das distribuições Linux, o Mac e Unix em geral). Não incluirei as explicações detalhadas, mas todos os mecanismos que usei hoje já estão explicados no post anterior: “Programando bots para o Mastodon: listando usuários via API” (e nos seus antecessores)
Hoje veremos um método baseado no ActivityPub, e outro que usa especificamente a API do Mastodon.
Quase todos os serviços on-line interativos conectados ao Fediverso respondem a chamadas básicas de identificação "NodeInfo", que estão definidas no protocolo ActivityPub, e um grande número deles também responde a chamadas bem mais detalhadas que fazem parte do protocolo Mastodon (com o qual vários outros serviços são compatíveis).
Veremos hoje como identificar um servidor a partir de cada uma das duas chamadas de identificação acima: a básica (do ActivityPub) e a detalhada (do Mastodon e seus compatíveis).
Usarei a minha própria instância (arram.senta-la.cloud) nos exemplos, mas você pode substituir pela que desejar consultar.
Identificação básica usando o ActivityPub
Como dito, o tipo de identificação "NodeInfo" funciona na grande maioria dos servidores interativos conectados ao Fediverso (incluindo Mastodon, Misskey, Lemmy, GoToSocial, Snac, Ghost, WordPress e mais), e ela tem 2 passos: (1) obter qual a URL de informações do servidor; e (2) obter as informações do servidor.
Passo 1. Para obter a URL de informações do servidor, é necessário consultar a sua url /.well-known/nodeinfo, como no exemplo:
gron "https://arram.senta-la.cloud/.well-known/nodeinfo"
json = {};
json.links = [];
json.links[0] = {};
json.links[0].href = "https://arram.senta-la.cloud/nodeinfo/2.0";
json.links[0].rel = "http://nodeinfo.diaspora.software/ns/schema/2.0";
Na listagem acima, o comando que eu digitei na shell interativa está em negrito, e as demais linhas são a resposta recebida. A linha que nos interessa é a penúltima, que define o href do link.
No exemplo acima, portanto, descobrimos que a URL de informações do servidor é https://arram.senta-la.cloud/nodeinfo/2.0. Agora que a conhecemos, podemos consultá-la também:
gron "https://arram.senta-la.cloud/nodeinfo/2.0"
json = {};
json.metadata = {};
json.metadata.nodeDescription = "arram.senta-la.cloud - A instância das trends, tags, efemérides e estatísticas no Fediverso BR. Bem-vindos à federação!";
json.metadata.nodeName = "Arram, senta lá, Cloud!";
json.openRegistrations = false;
json.protocols = [];
json.protocols[0] = "activitypub";
(...)
Novamente, o comando que eu digitei na shell interativa está em negrito, e as demais linhas são o início da resposta recebida, que eu cortei pois é extensa.
Note que as linhas retornadas apresentam várias informações sobre a minha instância, que roda o serviço Mastodon.
Para outros serviços (mesmo que sejam compatíveis com o Mastodon), os nomes dos atributos serão os mesmos, mas podem ser retornadas outros atributos (a menos, ou a mais) – por exemplo, se você inspecionar uma instância PeerTube, ela também retornará os formatos e resoluções de vídeo que ela suporta, e se você consultar uma instância Sharkey, ela retornará também o contato de seu admin (que o Mastodon não retorna nessa chamada).
O script a seguir realiza as duas consultas à minha instância e mostra o conteúdo de alguns atributos selecionados (que não necessariamente todas as instâncias retornarão ao responder a essa chamada):
#!/usr/bin/env bash
#
# instinfo_AP.sh - obtém via ActivityPub informações sobre uma instância
#
# Copyright (c) 2026, Augusto Campos (https://augustocampos.net/).
# Licensed under the Apache License, Version 2.0.
#
inst="https://arram.senta-la.cloud"
INFO_URL=$(curl -sL "$inst/.well-known/nodeinfo" |
gron | awk -F' = ' '/href/ {print $2}' | tr -d '";' | head -n 1)
curl -sL "$INFO_URL" | gron | awk -F' = ' '
/[.]nodeName/ {print "nome",$2}
/[.]nodeDescription/ && !/rules/ {print "descrição",$2}
/[.]software[.]name/ {print "sistema",$2}
/[.]software[.]version/ {print "versão",$2}
/[.]usage[.]users[.]total/ {print "usuários cadastrados",$2}
/[.]usage[.]users[.]activeMonth/ {print "usuários ativos",$2}
/[.]usage[.]localPosts/ {print "posts",$2}
'
Note que no script acima são feitos dois acessos ao servidor: o primeiro é para descobrir qual a URL de informações, e o segundo para consultá-la, retornando a seguir o conteúdo de alguns de seus atributos: o nome e descrição da instância, o nome e versão do software que está rodando nela, e algumas estatísticas básicas.
Nem todo servidor responde a essa chamada, mas ela funciona com a ampla maioria deles.
Se desejar, você pode modificar o script para tornar parametrizável, suportar mais (ou outros) atributos, e incluir tratamento de erro, por exemplo.
Identificação mais ampla usando a API do Mastodon
Além do próprio Mastodon, vários outros serviços do Fediverso (como o Snac, GoToSocial, WordPress e muitos outros) respondem a chamadas da API do Mastodon, de uma forma similar à que vimos acima, mas às vezes retornando mais informações.
Diferente do caso que vimos acima, fazer a consulta pela API do Mastodon envolve apenas uma chamada ao servidor, pela sua URL /api/v1/instance, como no exemplo:
gron "https://arram.senta-la.cloud/api/v1/instance"
json = {};
json.approval_required = false;
json.short_description = "arram.senta-la.cloud - A instância das trends, tags, efemérides e estatísticas no Fediverso BR. Bem-vindos à federação!";
json.stats = {};
json.stats.domain_count = 11027;
json.stats.status_count = 15863;
json.stats.user_count = 9;
json.title = "Arram, senta lá, Cloud!";
json.uri = "arram.senta-la.cloud";
json.version = "4.5.4";
Mais uma vez, o comando que eu digitei na shell interativa está em negrito, e as demais linhas são partes da resposta recebida, que eu cortei pois é extensa.
Ao fazer essa chamada a um servidor Mastodon, a resposta trará várias dezenas de atributos, descrevendo a instância, todas as suas regras, os detalhes sobre a conta de seu admin, a sua política quanto a aceitar ou não novas contas, quantos caracteres podem ter os seus posts, quantas alternativas podem ter as suas enquetes, e mais.
Novamente, ao fazermos a mesma chamada a outros tipos de servidores (compatíveis, mas que não estejam rodando o software Mastodon), os atributos terão os mesmos nomes, mas o conjunto pode ser diferente – por exemplo, uma instância Sharkey pode não retornar detalhes sobre seu admin, e uma instância Snac pode não listar suas regras.
O script a seguir realiza a consulta à minha instância e mostra o conteúdo de alguns atributos selecionados (que não necessariamente todas as instâncias compatíveis retornarão ao responder a essa chamada):
#!/usr/bin/env bash
#
# instinfo_MAS.sh - obtém via API Mastodon informações sobre uma instância
#
# Copyright (c) 2026, Augusto Campos (https://augustocampos.net/).
# Licensed under the Apache License, Version 2.0.
inst="https://arram.senta-la.cloud"
curl -sL "$inst/api/v1/instance" | gron | awk -F" = " '
/[.]title/ { print "título",$2 }
/[.](short_)?description/ { print "descrição",$2 }
/[.]languages\[/ { print "idioma",$2 }
/[.]contact_account[.]display_name/ { print "admin - nome",$2 }
/[.]contact_account[.]note/ { print "admin - nota",$2 }
/[.]contact_account[.]url/ { print "admin - url",$2 }
/[.]rules\[[0-9]+\][.](text|hint)/ {
gsub(/[";]/, "", $2);
regras = regras " - " $2
}
END { if (regras) print "regras",regras }
'
O script consulta a instância e retorna o conteúdo de alguns de seus atributos: o título e descrição da instância, idiomas visíveis na API, alguns detalhes sobre o admin, e o texto das regras (sem formatação).
Esses atributos foram escolhidos porque demonstram (se você testar com outras instâncias) que a resposta de outros serviços são diferentes das do Mastodon: por exemplo, testei com uma instância Misskey e, da lista acima, ela retornou apenas título e descrição. Testei com Snac e veio quase tudo, mas não as regras. E assim por diante.
Só os servidores compatíveis com a API do Mastodon (versão 1) respondem a essa chamada.
Se desejar, você pode modificar o script para tornar parametrizável, suportar mais (ou outros) atributos, formatar texto e incluir tratamento de erro, por exemplo.
E como identificar se o servidor é brasileiro?
Dependendo do seu interesse, essa pode ser a pergunta de um milhão de dólares, e infelizmente não tem resposta direta, porque depende inclusive de definir o que significa o servidor ser brasileiro: é estar hospedado no Brasil? Ter admin brasileiro? Ter maioria de usuários brasileiros? Ter maioria de posts originados em português?
A minha abordagem geral para essa pergunta é identificar se o servidor ou a conta do seu admin são descritos em português, e aí (caso eu esteja procurando por servidores brasileiros, e não mais amplamente por servidores lusófonos) excluir da lista os servidores que possam ser identificados como sendo de outros países.
Dependendo do caso, os próprios protocolos oferecem informações sobre o idioma dos textos - no exemplo acima da chamada da API do Mastodon, eu incluí o acesso ao atributo "language", inclusive. Infelizmente isso ajuda pouco, porque é muito frequente essa informação estar errada ou incompleta - e ela não distingue entre o português brasileiro, o europeu e o da África.
Para lidar com isso, eu uso uma heurística, ou regra de padeiro, em que reúno todos os textos retornados pela API nas chamadas acima (a descrição da instância, suas regras, a mensagem sobre autorização pra criar novas contas, os detalhes da conta do admin, e até as URLs), e procuro neles algumas caraterísticas comuns nesses textos quando se trata de instâncias brasileiras, como por exemplo:
- endereços que terminem com .br
- menções a Brasil ou Brazil, a português ou a portuguese, ou a pt_BR ou 🇧🇷.
- palavras como instância, comunidade, bem-vind, moderad, proibid, língua, regra, saiba
- palavras como você, aqui, também, não
- sufixos como ão, ões, inho, inha, ça, ço
Aplicar esse filtro é bastante eficaz, mas traz junto vários falsos positivos em italiano, francês, alemão, inglês, espanhol e galego (sendo que este último às vezes eu não desejo excluir, porque é uma língua tão próxima da nossa).
Antes de inspecionar manualmente, eu aplico um filtro que é eficaz para identificar a maior parte dos falsos positivos (i. e. servidores não-lusófonos identificados como brasileiros):
- palavras como cuenta, (y|el|los|las), de la, de lo, (un|el) servidor, serán, ningún
- palavras como información, hispano, contenido, habla, bienvenid, aplicables, proyecto
- palavras como kommen kontakt, réseau, communiquez, votre
- palavras como avéc, vous, lo, di, uno, unha, zum, wie, und, ein, zu, von
Note que as listas de palavras acima foram geradas empiricamente e a partir das estatísticas dos servidores reais do Fediverso, e podem não se aplicar a outros domínios.
Um pedido especial
A partir dos 2 scripts acima, e da heurística de identificação de origem/idioma, é possível implementar sistemas de coleta e análise de dados que responderão a questões interessantes sobre o Fediverso, e é por essa razão que eu os compartilho.
Porém, o Fediverso é composto de várias dezenas de milhares de servidores, muitos dos quais mantidos por voluntários que incorrem em custos de CPU e de tráfego. Respeite-os, não gere rotinas que os consultem com frequência exagerada, que os demandem de forma que os onere, e muito menos que tentem obter deles dados em desacordo com as suas políticas, termos e expectativas de privacidade.
Para saber mais sobre as ferramentas e técnicas aqui mencionadas, consulte os posts da tag Mastodon do meu blog.







