API grátis · português do Brasil · o texto não é guardado
Essa fala é livre de preconceito?
Escreva uma frase e veja, na hora, a resposta da API: se está tudo bem (free verdadeiro ou falso), qual é o tipo de problema e quanta certeza ela tem.
A resposta da API
A resposta aparece aqui
Escreva uma fala ao lado, ou escolha um exemplo, e a API mostra o veredito, o tipo e quanta certeza ela tem.
Não foi possível analisar agora
Tipos identificados
O texto, com os trechos que pesaram
O pedido e a resposta de verdade
O que o testador acabou de mandar e de receber. Copie o pedido e cole no seu terminal ou no seu código.
curl -X POST https://rodrigoborges.dev/api/sem-odio/analyze \
-H 'Content-Type: application/json' \
-d '{"text":"Todo negro é ladrão, essa gente não presta."}'Use no seu site ou app
Sem chave e sem cadastro, com CORS liberado para qualquer site. A resposta é sempre JSON. O texto enviado é analisado na memória e descartado: não é guardado, não vai para o log de acesso e não entra em nenhum contador.
Endereços
| Método | Endereço | O que faz | Custo |
|---|---|---|---|
| POST | /api/sem-odio/analyze | Analisa uma fala em JSON: { "text": "…", "threshold": 0.5 }. Devolve free, o tipo, a certeza e os trechos que pesaram. | por tamanho |
| GET | /api/sem-odio/analyze | O mesmo por GET (?text=…&threshold=…), para testar no navegador. Até 1000 caracteres; prefira o POST. | por tamanho |
| POST | /api/sem-odio/batch | Analisa até 20 falas de uma vez: { "texts": ["…", "…"] }. | soma dos textos |
| GET | /api/sem-odio/categories | Lista os tipos que a API identifica, com o id, o nome e a descrição. | 1 |
| GET | /api/sem-odio | Nome, versão, limites e a lista de endereços. | 1 |
| GET | /api/sem-odio/openapi.json | A especificação OpenAPI 3.1 desta API. | 1 |
Exemplo completo
Um POST com a fala em JSON. Com a nota de corte padrão (0.5) você não precisa mandar o threshold.
curl -X POST https://rodrigoborges.dev/api/sem-odio/analyze \
-H 'Content-Type: application/json' \
-d '{"text":"Todo negro é ladrão, essa gente não presta."}'const response = await fetch('https://rodrigoborges.dev/api/sem-odio/analyze', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ "text": "Todo negro é ladrão, essa gente não presta." }),
});
const result = await response.json();
console.log(result.free, result.type, result.confidence);import requests
result = requests.post(
'https://rodrigoborges.dev/api/sem-odio/analyze',
json={"text": "Todo negro é ladrão, essa gente não presta."},
timeout=10,
).json()
print(result['free'], result['type'], result['confidence'])O que mandar
| Campo | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
text | body/query | string | sim | A fala a analisar, em português do Brasil (1 a 5000 caracteres no POST, até 1000 no GET). |
texts | body | string[] | sim | Só no lote: de 1 a 20 textos de até 5000 caracteres, com no máximo 10000 no total. |
threshold | body/query | number | não | Nota de corte de 0,05 a 0,95 (padrão 0.5). Com nota (score) igual ou acima dela, free é false. Suba para tolerar mais; baixe para vigiar mais. |
O que volta
Cada análise devolve estes campos. No lote, cada item também leva o index do texto.
| Campo | Tipo | Descrição |
|---|---|---|
free | boolean | true se a fala está livre de preconceito e de discurso de ódio; false se não está. |
type | string | null | O tipo principal identificado (veja a lista de tipos). null quando free é true. |
label | string | null | O nome do tipo, em português. null quando free é true. |
confidence | number | Quanto o motor confia no veredito (free ou não), de 0 a 1. Se free é true, é a certeza de estar livre; se é false, a de não estar. |
percent | integer | A confidence em porcentagem, de 0 a 100. |
score | number | A chance estimada de a fala NÃO ser livre, de 0 a 1. É a nota que se compara com o threshold. |
threshold | number | A nota de corte usada: com score igual ou acima dela, free é false (padrão 0.5). |
types | object[] | Todos os tipos com nota a partir de 0,2, do maior para o menor: { id, label, score }. |
matches | object[] | Os trechos que pesaram: { start, end, text, type, reason, weight }. start e end são posições no texto enviado; reason diz o motivo e weight o peso do trecho. |
language | string | Sempre "pt-BR". |
version | string | A versão do motor. |
Tipos identificados (type)
| id | Nome | O que cobre |
|---|---|---|
racismo | Racismo | Ofensa, estereótipo ou ódio contra pessoas por raça, cor, etnia ou origem (negros, indígenas, asiáticos, ciganos). |
lgbtfobia | LGBTfobia | Ofensa, estereótipo ou ódio contra pessoas por orientação sexual ou identidade de gênero (gays, lésbicas, bissexuais, pessoas trans). |
misoginia | Misoginia e sexismo | Ofensa, estereótipo ou ódio contra mulheres por serem mulheres. |
xenofobia | Xenofobia | Ofensa, estereótipo ou ódio contra pessoas por nacionalidade ou região (nordestinos, imigrantes, refugiados). |
intolerancia_religiosa | Intolerância religiosa | Ofensa, estereótipo ou ódio contra pessoas por religião ou crença, e antissemitismo (judeus, muçulmanos, religiões de matriz africana, evangélicos). |
capacitismo | Capacitismo | Ofensa ou estereótipo contra pessoas com deficiência, ou o uso de uma condição como xingamento. |
gordofobia | Gordofobia | Ofensa, estereótipo ou ódio contra pessoas por causa do peso ou do corpo. |
etarismo | Etarismo | Ofensa, estereótipo ou ódio contra pessoas por causa da idade, em geral idosos. |
classismo | Classismo | Ofensa, estereótipo ou ódio contra pessoas por classe social (pobres, favelados, pessoas em situação de rua). |
intolerancia_politica | Intolerância política | Ofensa, estereótipo ou ódio contra pessoas por posição política ou partido ("todo petista é burro", "a direita é fascista"): critica-se a ideia, não se ataca todo mundo que a defende. |
ameaca | Ameaça e incitação à violência | Ameaça de morte ou de agressão, desejo de que alguém morra ou se machuque, e incentivo à violência. |
ofensa | Ofensa e xingamento | Insulto dirigido a uma pessoa, sem mirar um grupo (idiota, babaca, "vai tomar no…"). |
Motivos dos trechos (reason)
| reason | Significa |
|---|---|
slur | Termo ofensivo contra um grupo |
generalization | Generalização depreciativa sobre um grupo |
dehumanization | Compara um grupo a algo desumano |
stereotype | Estereótipo ofensivo |
hate | Expressão de ódio contra um grupo |
violence | Incitação à violência contra um grupo |
exclusion | Exclusão ou negação de direitos |
threat | Ameaça |
insult | Insulto dirigido a alguém |
phrase | Expressão preconceituosa conhecida |
disclaimer | Ressalva típica de quem vai ofender ("não sou racista, mas…") |
Limites e erros
Cada IP tem 120 pontos por minuto e 2000 por hora. Um texto custa 1 ponto a cada 500 caracteres (no mínimo 1). Os cabeçalhos RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset dizem quanto ainda cabe; passou do limite, vem 429 com Retry-After. Cada texto aceita até 5000 caracteres no POST (1000 no GET) e um lote, até 20 textos e 10000 caracteres no total.
code | HTTP | Quando |
|---|---|---|
missing_text | 400 | Envie o campo "text" com a fala a analisar. |
invalid_text | 400 | O campo "text" precisa ser um texto. |
text_too_long | 413 | O texto passa de 5000 caracteres. |
get_text_too_long | 414 | Para texto com mais de 1000 caracteres use POST. |
missing_texts | 400 | Envie o campo "texts" com a lista de falas a analisar. |
invalid_texts | 400 | O campo "texts" precisa ser uma lista de textos. |
batch_too_large | 413 | O lote passa de 20 textos ou de 10000 caracteres. |
invalid_param | 400 | Há um parâmetro inválido. |
bad_request | 400 | O corpo do pedido não é um JSON válido. |
too_large | 413 | O corpo do pedido é grande demais. |
uri_too_long | 414 | Endereço longo demais. |
rate_limited | 429 | Muitos pedidos em pouco tempo. |
method_not_allowed | 405 | Método não permitido neste endereço. |
not_found | 404 | Endereço não encontrado. |
Todo erro vem em JSON: { "error": "…", "code": "…" }. A mensagem nunca repete o que você mandou. A especificação completa está em openapi.json (OpenAPI 3.1).
Como ele decide, e onde erra
O motor não é um modelo de aprendizado: é um léxico de palavras e expressões com regras de contexto escritas à mão. Uma palavra de grupo (“mulheres”, “gays”) sozinha não pesa; pesa quando vem com uma frase depreciativa, um ódio declarado, uma ameaça ou uma exclusão. Negação, citação e denúncia derrubam o peso. A confidence é uma estimativa do motor, calibrada num conjunto de testes pequeno e escrito pelo próprio autor: não é uma probabilidade estatística.
- Ele não entende ironia, humor nem códigos de grupo: o que não está no léxico passa como livre.
- Ele erra para os dois lados: pode deixar passar uma ofensa nova e pode marcar uma frase que cita um termo sem ofender.
- Só funciona em português do Brasil.
- Use como primeira triagem, com uma pessoa decidindo o que é apagado ou punido.
Números abertos
- Textos analisados
- 0
- Sinalizados
- 0
- Livres de ódio
- 0
- Tipo mais frequente
- —
- Pedidos à API
- 0
- Feitos pelo testador
- 0
- Pedidos barrados
- 0
Só contagens, nunca uma fala. Contando desde 29/10/2026.