---
title: "Como publicar notícias de um feed RSS em um canal do Discord"
description: "Publique notícias de um feed RSS em um canal do Discord com rss-parser, sem repetir itens, com embed e consulta educada. Inclui a opção com webhook."
url: "https://streethosting.com.br/guias/bots-discord/bot-discord-feed-rss-noticias"
category: "bots-discord"
slug: "bot-discord-feed-rss-noticias"
datePublished: "2026-11-13"
dateModified: "2026-11-13"
author: "Equipe StreetHosting"
difficulty: "intermediario"
language: "pt-BR"
keywords:
  - "bot discord feed rss noticias"
  - "discord.js rss-parser"
  - "postar feed rss no discord"
  - "bot discord notícias automáticas"
  - "webhook discord feed rss"
---

# Bot Discord com feed RSS: notícias automáticas no canal

Aprenda a ler um feed RSS com a biblioteca rss-parser, guardar o último item visto, consultar sem sobrecarregar o site e postar cada notícia em um embed com título e link.

> **Resposta rápida**
>
> Instale o `rss-parser`, leia o feed a cada 10 a 30 minutos, compare o `guid` de cada item com os já vistos e poste só os novos em um embed com título e link. Salve os itens vistos em arquivo para o bot não repetir notícia depois de reiniciar. Sem bot, dá para usar um webhook, desde que algo consulte o feed e dispare a mensagem.

## Como o feed vira mensagem

Um feed RSS é um arquivo que o site atualiza sempre que publica algo novo. Dentro dele existe uma lista de itens, cada um com título, link, data e um resumo. Seu bot baixa esse arquivo de tempos em tempos, descobre quais itens ele ainda não postou e manda cada um como mensagem no canal.

O trabalho se divide em três partes: ler o feed, lembrar o que já foi postado e montar a mensagem. Este guia usa discord.js v14 e Node 20 ou mais novo. Se você ainda não tem um bot, comece pelo guia de [criar o primeiro bot Discord do zero](https://streethosting.com.br/guias/bots-discord/criar-primeiro-bot-discord-do-zero). O bot só envia mensagens, então a intent Guilds é suficiente.

Vale uma observação sobre conteúdo. Poste título, um resumo curto e o link para o texto original. Copiar a matéria inteira para o Discord não é educado com quem escreveu e pode dar problema de direitos autorais. O link leva a audiência de volta ao site.

## Ler o feed com rss-parser

Instale a biblioteca com `npm install rss-parser`. Ela baixa o arquivo, entende RSS e Atom e devolve os itens já organizados.

```
const Parser = require('rss-parser');
const parser = new Parser();

async function teste() {
  const feed = await parser.parseURL('https://exemplo.com/feed.xml');

  console.log(feed.title);
  for (const item of feed.items.slice(0, 3)) {
    console.log(item.title, item.link, item.guid, item.isoDate);
  }
}

teste();
```

Rode isso antes de mexer no Discord. Cada item traz `title`, `link`, `guid`, `isoDate` e `contentSnippet`, que é o resumo sem HTML. Em feed Atom o identificador vem em `id` no lugar de `guid`. Se der erro dizendo que o conteúdo não parece um feed, o endereço provavelmente aponta para uma página comum e não para o arquivo do feed.

## Guardar o último item visto

O identificador de cada item é o **guid** nos feeds RSS e o **id** nos feeds Atom. Alguns feeds não preenchem esse campo, então use o link como última opção, como faz a função `chave` do código completo. A regra é simples: um item é novo quando o identificador dele não está na lista dos já vistos.

Por que uma lista e não só o último id? Porque a ordem dos itens no feed nem sempre é a que você espera, e porque o site pode apagar a notícia mais recente. Com uma lista dos últimos 100 identificadores, o bot continua acertando nesses casos.

- Na primeira execução de um feed, memorize todos os itens atuais sem postar nenhum.
- Nas execuções seguintes, poste apenas o que não está na lista.
- Poste do mais antigo para o mais novo, para o canal ficar em ordem cronológica.
- Salve a lista em arquivo, para ela sobreviver a um reinício.

> **Atenção**
>
> Alguns sites mudam o guid de uma notícia quando a editam. Se o seu bot começar a repetir matérias, troque a chave para o link do item. Na maioria dos casos o link é mais estável.

## Consultar com educação

O feed pertence a um site que paga pelo tráfego. Um bot que baixa o arquivo a cada poucos segundos incomoda esse site e pode ser bloqueado. Algumas regras boas:

- Use um intervalo de 10 a 30 minutos. Para a maioria dos sites de notícia, isso é mais que suficiente.
- Identifique o bot no cabeçalho `User-Agent`, com nome e um contato, para o dono do site saber quem está acessando.
- Use consulta condicional: guarde o `ETag` e o `Last-Modified` da última resposta e envie de volta. Se nada mudou, o site responde 304 sem mandar o arquivo.
- Coloque um tempo limite na requisição, para um site lento não travar o seu bot.
- Consulte os feeds um de cada vez, não todos no mesmo instante.

Para usar a consulta condicional, baixe o arquivo com `fetch` e entregue o texto ao parser com `parseString`. É o que o código completo da próxima seção faz.

## O bot completo com embed

O código abaixo junta tudo: vários feeds, cada um com o seu canal, lista de itens vistos salva em arquivo, consulta condicional e um embed por notícia com título clicável, resumo curto e data. Para o embed ficar mais caprichado, veja também o guia sobre [embeds e mensagens formatadas](https://streethosting.com.br/guias/bots-discord/bot-discord-embeds-mensagens-formatadas).

```
const fs = require('node:fs');
const Parser = require('rss-parser');
const { Client, Events, GatewayIntentBits, EmbedBuilder } = require('discord.js');

const FEEDS = [
  {
    nome: 'Site de exemplo',
    url: 'https://exemplo.com/feed.xml',
    canalId: process.env.CANAL_NOTICIAS_ID,
  },
];

const ARQUIVO_ESTADO = './estado-feeds.json';
const INTERVALO = 15 * 60 * 1000;
const parser = new Parser();
const client = new Client({ intents: [GatewayIntentBits.Guilds] });

function lerEstado() {
  try {
    return JSON.parse(fs.readFileSync(ARQUIVO_ESTADO, 'utf8'));
  } catch {
    return {};
  }
}

function salvarEstado(estado) {
  fs.writeFileSync(ARQUIVO_ESTADO, JSON.stringify(estado, null, 2));
}

const chave = (item) => item.guid || item.id || item.link;

async function baixarFeed(url, cache) {
  const headers = { 'User-Agent': 'MeuBotNoticias/1.0 (contato: voce@exemplo.com)' };
  if (cache.etag) headers['If-None-Match'] = cache.etag;
  if (cache.modified) headers['If-Modified-Since'] = cache.modified;

  const resp = await fetch(url, { headers, signal: AbortSignal.timeout(15000) });
  if (resp.status === 304) return null;
  if (!resp.ok) throw new Error(`Feed respondeu ${resp.status}`);

  return {
    dados: await parser.parseString(await resp.text()),
    etag: resp.headers.get('etag'),
    modified: resp.headers.get('last-modified'),
  };
}

function montarEmbed(feed, item) {
  const embed = new EmbedBuilder()
    .setColor(0xff6a00)
    .setTitle((item.title || 'Sem título').slice(0, 256))
    .setURL(item.link)
    .setFooter({ text: feed.nome });

  if (item.contentSnippet) {
    embed.setDescription(item.contentSnippet.slice(0, 300));
  }
  if (item.isoDate) embed.setTimestamp(new Date(item.isoDate));
  return embed;
}

async function checarFeed(feed, estado) {
  const cache = estado[feed.url] ?? (estado[feed.url] = { vistos: [] });
  const baixado = await baixarFeed(feed.url, cache);
  if (!baixado) return; // 304: nada mudou

  const primeiraVez = cache.vistos.length === 0;
  const novos = baixado.dados.items.filter(
    (item) => chave(item) && !cache.vistos.includes(chave(item))
  );

  const canal = await client.channels.fetch(feed.canalId);

  for (const item of novos.reverse()) {
    if (!primeiraVez) await canal.send({ embeds: [montarEmbed(feed, item)] });
    cache.vistos.unshift(chave(item));
  }

  cache.vistos = cache.vistos.slice(0, 100);
  cache.etag = baixado.etag;
  cache.modified = baixado.modified;
}

let rodando = false;

async function rodar() {
  if (rodando) return;
  rodando = true;

  const estado = lerEstado();
  for (const feed of FEEDS) {
    try {
      await checarFeed(feed, estado);
    } catch (err) {
      console.error(`Erro no feed ${feed.nome}:`, err.message);
    } finally {
      salvarEstado(estado);
    }
  }

  rodando = false;
}

client.once(Events.ClientReady, () => {
  rodar();
  setInterval(rodar, INTERVALO);
});

client.login(process.env.DISCORD_TOKEN);
```

Dois cuidados no código. O `slice` nos textos respeita os limites do embed, que aceita até 256 caracteres no título e 4096 na descrição. E o ETag só é atualizado depois de postar tudo, então se o envio falhar no meio, a próxima consulta tenta de novo em vez de achar que não há nada novo.

> **Dica**
>
> Quer uma notícia por mensagem simples, sem embed? Troque o envio por `canal.send(item.link)`. O Discord monta a prévia do link sozinho, e o resultado funciona bem em canais de notícia.

## Alternativa sem bot: webhook

Se você não quer manter um bot só para isso, o Discord permite criar um webhook no canal. Nas configurações do canal, em Integrações, crie um webhook e copie o endereço. Qualquer programa que fizer um POST nesse endereço publica uma mensagem no canal, sem login de bot e sem intents. O guia de [webhook do Discord para alertas](https://streethosting.com.br/guias/bots-discord/webhook-discord-alertas-servidor) mostra o formato com mais detalhes.

```
await fetch(process.env.WEBHOOK_URL, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    embeds: [{
      title: (item.title || 'Sem título').slice(0, 256),
      url: item.link,
      description: (item.contentSnippet || '').slice(0, 300),
      color: 0xff6a00,
    }],
  }),
});
```

O detalhe é que o webhook só recebe, ele não consulta o feed. Alguma coisa precisa fazer a leitura do RSS e a lógica de itens novos. Pode ser o mesmo script deste guia, trocando o `canal.send` pelo POST acima e rodando por agendamento, ou uma automação pronta no n8n, que tem nó de RSS e de Discord. Se for por esse caminho, o guia de [hospedar o n8n em uma VPS](https://streethosting.com.br/guias/vps/hospedar-n8n-vps-brasil) ajuda. A desvantagem do webhook é que você perde comandos, botões e qualquer interação. Para só empurrar notícias, ele resolve.

## Onde rodar na StreetHosting

O bot de notícias precisa ficar ligado, porque é o processo dele que consulta os feeds no intervalo. Na [hospedagem de bots da StreetHosting](https://streethosting.com.br/bots) ele roda em um container Node.js com painel, e o plano Discord Essential, por R$ 9,99/mês, com 1 GB de RAM, sobra para esse tipo de bot, que passa quase o tempo todo parado esperando o próximo intervalo.

Deixe o arquivo de estado na pasta do bot e configure as variáveis de ambiente pelo painel. Para o mesmo padrão de consulta periódica com outra fonte de dados, veja o guia de [notificação de live da Twitch e YouTube](https://streethosting.com.br/guias/bots-discord/bot-discord-notificacao-live-twitch-youtube). E se quiser entender as opções de hospedagem, leia [hospedagem de bot Discord 24/7](https://streethosting.com.br/guias/bots-discord/hospedagem-bot-discord-24-7).

## Perguntas frequentes

### O que é um feed RSS e onde encontro o endereço?

É um arquivo que o site mantém com a lista dos conteúdos mais recentes, em formato fácil para programas lerem. O endereço costuma terminar em feed, rss ou feed.xml, e muitos sites mostram um ícone ou link de RSS no rodapé. Se não achar, procure no código da página por rss ou atom.

### Qual intervalo de consulta devo usar?

Para notícias, entre 10 e 30 minutos é um intervalo educado. Consultar a cada poucos segundos não deixa o aviso mais rápido, porque a maioria dos sites atualiza o feed de tempos em tempos, e pode fazer o site bloquear o seu bot.

### Por que o bot repetiu notícias antigas depois de reiniciar?

Porque o controle dos itens já vistos estava só na memória. Salve em arquivo ou em banco de dados, e na primeira execução apenas memorize os itens atuais sem postar, para o bot não despejar o feed inteiro no canal.

### O rss-parser lê feeds Atom também?

Sim. A biblioteca entende RSS e Atom e entrega os itens em um formato parecido nos dois casos, com campos como title, link e isoDate. A diferença está no identificador: ele vem em guid nos feeds RSS e em id nos feeds Atom.

### Dá para postar feed RSS no Discord sem criar um bot?

Dá, usando um webhook do canal. Mas o webhook só recebe mensagens, ele não consulta o feed sozinho. Você ainda precisa de algo que verifique o RSS e faça a chamada, como um script agendado ou uma automação no n8n.

## Guias relacionados

- [Como avisar no Discord quando um streamer entra ao vivo na Twitch ou no YouTube](https://streethosting.com.br/guias/bots-discord/bot-discord-notificacao-live-twitch-youtube.md)
- [Como usar webhook do Discord para alertas de servidor](https://streethosting.com.br/guias/bots-discord/webhook-discord-alertas-servidor.md)
- [Embeds no Discord com discord.js: como montar mensagens formatadas](https://streethosting.com.br/guias/bots-discord/bot-discord-embeds-mensagens-formatadas.md)
- [Hospedagem de bot Discord 24/7 no Brasil](https://streethosting.com.br/guias/bots-discord/hospedagem-bot-discord-24-7.md)

## Produtos citados

- https://streethosting.com.br/bots

## Dados estruturados

```json
[
  {
    "@context": "https://schema.org",
    "@type": [
      "Article",
      "TechArticle"
    ],
    "headline": "Bot Discord com feed RSS: notícias automáticas no canal",
    "name": "Como publicar notícias de um feed RSS em um canal do Discord",
    "abstract": "Aprenda a ler um feed RSS com a biblioteca rss-parser, guardar o último item visto, consultar sem sobrecarregar o site e postar cada notícia em um embed com título e link.",
    "description": "Publique notícias de um feed RSS em um canal do Discord com rss-parser, sem repetir itens, com embed e consulta educada. Inclui a opção com webhook.",
    "datePublished": "2026-11-13",
    "dateModified": "2026-11-13",
    "author": {
      "@type": "Organization",
      "name": "Equipe StreetHosting"
    },
    "publisher": {
      "@type": "Organization",
      "name": "StreetHosting",
      "url": "https://streethosting.com.br"
    },
    "inLanguage": "pt-BR",
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://streethosting.com.br/guias/bots-discord/bot-discord-feed-rss-noticias"
    }
  },
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {
        "@type": "Question",
        "name": "O que é um feed RSS e onde encontro o endereço?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "É um arquivo que o site mantém com a lista dos conteúdos mais recentes, em formato fácil para programas lerem. O endereço costuma terminar em feed, rss ou feed.xml, e muitos sites mostram um ícone ou link de RSS no rodapé. Se não achar, procure no código da página por rss ou atom."
        }
      },
      {
        "@type": "Question",
        "name": "Qual intervalo de consulta devo usar?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Para notícias, entre 10 e 30 minutos é um intervalo educado. Consultar a cada poucos segundos não deixa o aviso mais rápido, porque a maioria dos sites atualiza o feed de tempos em tempos, e pode fazer o site bloquear o seu bot."
        }
      },
      {
        "@type": "Question",
        "name": "Por que o bot repetiu notícias antigas depois de reiniciar?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Porque o controle dos itens já vistos estava só na memória. Salve em arquivo ou em banco de dados, e na primeira execução apenas memorize os itens atuais sem postar, para o bot não despejar o feed inteiro no canal."
        }
      },
      {
        "@type": "Question",
        "name": "O rss-parser lê feeds Atom também?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Sim. A biblioteca entende RSS e Atom e entrega os itens em um formato parecido nos dois casos, com campos como title, link e isoDate. A diferença está no identificador: ele vem em guid nos feeds RSS e em id nos feeds Atom."
        }
      },
      {
        "@type": "Question",
        "name": "Dá para postar feed RSS no Discord sem criar um bot?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Dá, usando um webhook do canal. Mas o webhook só recebe mensagens, ele não consulta o feed sozinho. Você ainda precisa de algo que verifique o RSS e faça a chamada, como um script agendado ou uma automação no n8n."
        }
      }
    ]
  }
]
```
