Founding customers get 50% off the first year. Claim it →
← all posts

Google News RSS returns 503 from a server

November 5, 202612 min readFeedmarkdown#google-news#rss#troubleshooting#n8n#rate-limits

Illustration of a small courier robot with a rolled newspaper standing at a closed gate, and the same robot walking through an open side door in the wall

A Google News RSS 503 from a server, with a short "Sorry..." HTML body, that works fine from your laptop is most likely an IP-based block on the address your job runs from. The one measurement we found says so, though reports are few. The fastest check is to run the same curl from your laptop and from the job at the same minute, and compare status and body size. The fixes: fetch from another IP, poll less and fail soft, or use another source. See the options with the tradeoffs.

Feedmarkdown runs the Google News fetch, link resolving and scraping on its own servers. Your n8n, Worker or Action only receives a signed webhook or pulls a feed, and failures show per source. More in the last section.

For the URL formats, see the Google News RSS feed guide. Anything dated 2026-11-05 below, we ran. The rest comes from public reports that we link. We could not reproduce the 503.

What the 503 looks like

In n8n's RSS Read node it is Status code 503. In Make it is ConnectionError and Service Unavailable. A Cloudflare Worker fetch gets a 503 response with a 1,103-byte body.

The only 503 body we found quoted is in a Make community thread from June 2026. It reads "We're sorry" and then "but your computer or network may be sending automated queries. To protect our users, we can't process your request right now." Pages about this error sometimes mention "unusual traffic". As far as we could tell that wording is from Google's search sorry page, not from this News body.

Look-alikes that are not this one:

    1. The gnews-decoder docs and a cloudspress guide report it mostly on the per-article decode step, not the feed. In our scraping test we saw none on the feed or the redirect call, though the HTML search page did return 429.
  • An empty 302. Topic URLs under /rss/headlines/section/topic/ redirect to /rss/topics/<id>. A client that does not follow redirects sees an empty body.
  • A 200 with HTML. An article link fetched without a browser returns Google News's JavaScript app shell.

Why a server gets it and a laptop does not

The clearest measurement is issue 6 on oliverames/cerulean-news, dated 2026-09-16. It says:

news.google.com answers a Worker with HTTP 503 and Google's "Sorry..." interstitial (1,103 bytes, ~5-10s latency). The same URLs return 200 from a laptop. It is IP reputation, not headers.

Their table has two search URLs returning 503 and 1,103 bytes from the Worker, for example against 200 with 124,705 bytes from a laptop. The publisher's own feed returned 200 from the same Worker.

A thread on the n8n community forum from 2026-04-28 points the same way. The poster, on n8n Cloud, wrote that "the gap of each request is 2-3 minutes and I just sends only 4 request at a time" and was still blocked. One reply guessed a rate limit. Another called it "a flat IP block" on datacenter addresses, an unconfirmed opinion. The thread closed with no confirmed fix.

The Make poster said the HTTP module "worked a few times, but then it failed again". That fits a per-IP block that comes and goes. Our guess, and only a guess, is that shared IP pools inherit the history of other tenants.

Check it in two minutes

Run one request from your laptop and one from where the job runs, in the same minute. A 503 can also be a real outage, so you need both. Compare status, content type, size and the first bytes.

URL='https://news.google.com/rss/search?q=offshore+wind&hl=en-US&gl=US&ceid=US:en'
date -u
curl -s -o gn.xml \
  -w 'status=%{http_code}\ncontent_type=%{content_type}\nbytes=%{size_download}\nremote_ip=%{remote_ip}\ntotal_s=%{time_total}\n' \
  "$URL"
head -c 300 gn.xml

This is the output from our laptop on 2026-11-05, the healthy case. We have no 503 of our own to show. Sizes drift a little between requests: the same laptop got 132718 bytes at 15:08 and 130541 at 15:33.

Thu Nov  5 15:33:07 UTC 2026
status=200
content_type=application/xml; charset=utf-8
bytes=130541
remote_ip=142.251.209.238
total_s=0.455646
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><generator>NFE/5.0</generator><title>"offshore wind" - Google News</title><link>https://news.google.com/search?q=offshore+wind&amp;hl=en-US&amp;gl=US&amp;ceid=US:en</link><l

Healthy case: terminal output of the curl check on a laptop on 2026-11-05, status 200, content type application/xml, 130541 bytes, then the start of the RSS XML

How to read the result:

You get Likely meaning Do this
200, application/xml, tens of KB or more The feed works from here Look at your parser
503, text/html, about 1 KB, body contains "Sorry" Likely an IP block. One report measured 1,103 bytes See the options below
503 from the laptop too Possibly a real outage Wait and retry
429 Rate limit Back off
302, empty body A redirect you did not follow Use curl -L or enable redirects
200, text/html, about 600 KB Google News's app shell for an article link, not the feed Fetch the RSS URL

Sizes are what we and the reports saw, not a contract. If you got a 503, jump to the options.

To run the same check where the job lives:

  • GitHub Actions: the curl above plus curl -s https://ipinfo.io/org, which shows the network your runner sits on.
  • n8n: an HTTP Request node with the response status included and "never error" on, then an IF node on statusCode.
  • A Cloudflare Worker: the snippet below. We only checked that it parses. Running it with wrangler dev sends the request from your own machine, so that run tells you nothing about Workers.
export default {
  async fetch() {
    const url = "https://news.google.com/rss/search?q=offshore+wind&hl=en-US&gl=US&ceid=US:en";
    const res = await fetch(url);
    const body = await res.arrayBuffer();
    return Response.json({
      status: res.status,
      contentType: res.headers.get("content-type"),
      bytes: body.byteLength,
      head: new TextDecoder().decode(body.slice(0, 200)),
    });
  },
};

Google News RSS 503 on n8n Cloud, Cloudflare Workers and GitHub Actions

Google News RSS not working on n8n Cloud

One community report: n8n 2.17.5, the RSS Read node returned 503, and the poster said the HTTP Request node was blocked too.

Google News 503 from Cloudflare Workers

Our only evidence is the cerulean-news issue above. In that issue the same 503 came back for the default user agent, for a full Chrome user agent with accept and accept-language, and for another endpoint (/rss/headlines/section/topic/HEALTH).

A full Worker run reported 38 unhealthy sources, 36 of them 503s from Google News. The last successful Actions run, on 2026-09-05, reported 1. Decoding article links was refused too: "a run spent 8.3 minutes in enrichment and completed exactly 1 article fetch". Browser Rendering, they wrote, "egresses from the same network".

Google News RSS 503 on GitHub Actions

In london-lions issue 25, a probe on a hosted runner (AS8075, Microsoft) got 200 from every candidate on 2026-10-23. The author adds: "One run is not proof it never happens".

We ran our own probe on 2026-11-05: three workflow runs with ubuntu and macOS jobs (one macOS job never started), about five runner IPs on AS8075 (Azure) and AS14618 (AWS). Each job made up to 9 requests, 5 seconds apart. Run 1 skipped the article step because of a script bug.

Every search feed URL answered 200 with application/xml, about 132 KB. Topic URLs answered 302 to /rss/topics/<id>, and 200 once redirects were followed. Our laptop in the Netherlands got the same. We saw no 503, no 429 and no sorry page. A sandbox on OVH (AS16276) at 15:45 UTC, with 4 requests, also got 200 application/xml (131,126 bytes) for the search feed with the default and a Chrome user agent, and a 302 for the topic URL.

So Azure, AWS and OVH all answered 200 that day. Whether a block hits depends on the IP range and the moment, as cerulean's Workers result shows.

Terminal-style table of the GitHub Actions runs and laptop on 2026-11-05: a laptop and five GitHub Actions jobs on Azure and AWS networks all got 200 application/xml for the search feed, about 132 KB

The workflow is below. Run it once by hand with workflow_dispatch, not on a schedule.

name: probe
on: workflow_dispatch
jobs:
  probe:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Probe news.google.com RSS
        shell: bash
        run: |
          mkdir -p out
          date -u
          echo "runner: ${{ matrix.os }}"
          echo "ip: $(curl -s https://api.ipify.org)"
          echo "org: $(curl -s https://ipinfo.io/org)"
          BUA='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'
          S='https://news.google.com/rss/search?q=offshore+wind&hl=en-US&gl=US&ceid=US:en'
          T='https://news.google.com/rss/headlines/section/topic/TECHNOLOGY?hl=en-US&gl=US&ceid=US:en'
          probe() { # name url ua L
            echo "--- $1"
            if [ -n "$4" ]; then L=-L; else L=; fi
            curl -s $L -A "$3" -o "out/$1.txt" -w '%{http_code} %{content_type} %{size_download} %{url_effective}\n' "$2"
            head -c 600 "out/$1.txt"; echo
            sleep 5
          }
          probe search_default "$S" curl/8.5.0
          probe search_browser "$S" "$BUA"
          probe search_browser_L "$S" "$BUA" L
          probe topic_default "$T" curl/8.5.0
          probe topic_browser "$T" "$BUA"
          probe topic_browser_L "$T" "$BUA" L
          A=$(sed 's/></>\n</g' out/search_browser_L.txt | grep -m1 -o 'https://news.google.com/rss/articles/[^<"]*' || true)
          echo "article url: $A"
          set +e
          probe art_default "$A" curl/8.5.0
          probe art_browser "$A" "$BUA"
          probe art_browser_L "$A" "$BUA" L
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: bodies-${{ matrix.os }}
          path: out/

Hosted runners worked on the days we and london-lions tried. That does not make them safe: five polite requests per IP say nothing about a busy shared pool over days. We found no credible report for Vercel, AWS Lambda, Render, Fly or a plain VPS, so we claim nothing either way.

What did not help in other people's reports

  • Headers and endpoint. Changing the user agent, adding accept headers or switching endpoint did not help in the cerulean test. It is the only such test we found.
  • The HTTP node instead of the RSS node. The n8n poster said both were blocked. The Make user said the HTTP module "worked a few times, but then it failed again".
  • Low volume. The n8n poster sent 4 requests at a time, with 2 to 3 minutes between requests, by their own account.

The Make thread quotes a third party saying a 15 to 30 minute interval is safe for most use cases. We could not verify that. From a home IP, 270 polite requests all returned 200 in our scraping test, which tried no datacentre address. The probe above only partly fills that gap.

Options, with the tradeoffs

Relay through another IP

Send the Google News request through a machine whose address Google accepts, such as a home server. Cerulean did this with a container on a home server, reached over a tunnel. It accepted GET only, news.google.com only, and required a bearer token. They reported healthy sources going from 59 of 97 to 96 of 97, and the run from 625 s to 151 s. That is their result, not ours.

Here is a minimal relay in the same shape, in standard-library Python. Set RELAY_TOKEN to a long random value and run it on 127.0.0.1. It checks the token, allows only https://news.google.com/rss/ URLs, caches good responses for 10 minutes and passes Google's status through. One catch: Python's urllib follows redirects, so the allowlist checks only the requested URL. Topic feeds redirect within news.google.com, which is fine, but an off-host redirect, for example to consent.google.com, would also be followed.

"""Home relay: fetch Google News RSS from a residential IP on behalf of a cloud caller."""
import hmac, os, time, urllib.request, urllib.error
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import urlparse, parse_qs

TOKEN = os.environ["RELAY_TOKEN"]
CACHE, TTL = {}, 600  # url -> (expires, status, body, content_type)

class Relay(BaseHTTPRequestHandler):
    log_message = lambda *a: None
    def reply(self, status, body=b"", ctype="text/plain", cache="MISS"):
        self.send_response(status)
        self.send_header("Content-Type", ctype)
        self.send_header("X-Relay-Cache", cache)
        self.end_headers()
        self.wfile.write(body)

    def do_GET(self):
        auth = self.headers.get("Authorization", "")
        if not hmac.compare_digest(auth.encode(), f"Bearer {TOKEN}".encode()):
            return self.reply(401, b"unauthorized")
        u = urlparse(self.path)
        target = (parse_qs(u.query).get("url") or [""])[0]
        t = urlparse(target)
        # hard allowlist: https://news.google.com/rss/... only
        if u.path != "/rss" or t.scheme != "https" or t.hostname != "news.google.com" \
                or t.port or t.username or not t.path.startswith("/rss/"):
            return self.reply(400, b"only https://news.google.com/rss/ allowed")
        hit = CACHE.get(target)
        if hit and hit[0] > time.time():
            return self.reply(*hit[1:], cache="HIT")
        try:
            r = urllib.request.urlopen(urllib.request.Request(target), timeout=20)
        except urllib.error.HTTPError as e:
            r = e
        except Exception:
            return self.reply(502, b"upstream error")
        status, ctype, body = r.status if hasattr(r, "status") else r.code, \
            r.headers.get("Content-Type", "application/xml"), r.read()
        if status == 200:
            CACHE[target] = (time.time() + TTL, status, body, ctype)
        self.reply(status, body, ctype)

ThreadingHTTPServer(("127.0.0.1", int(os.environ.get("PORT", 8787))), Relay).serve_forever()

We tested it locally on a home connection on 2026-11-05 at 15:45 UTC. The first request returned X-Relay-Cache: MISS, the second HIT, both 200 with 131,126 bytes. We did not test the tunnel.

In an n8n HTTP Request node, use GET, the URL https://YOUR-TUNNEL-HOST/rss?url={{ encodeURIComponent($json.feedUrl) }}, and a Header Auth credential with Authorization: Bearer YOUR_RELAY_TOKEN. Pass the XML to an RSS Read or XML node.

Expose the relay only through a tunnel such as Cloudflare Tunnel or Tailscale Funnel, never an opened router port. Keep the allowlist, or it becomes an open proxy. Rotate the token regularly.

The article-link decode has to go through the relay too. Our redirect post covers that step. A residential proxy is a paid third-party service.

Run the job elsewhere

Self-hosted n8n, or a self-hosted runner on a network that works today. Hosted Actions worked on the days we tried, with no promise about tomorrow.

Poll less, cache and fail soft

Use a longer interval and keep the last good XML. Handle errors per source so one 503 does not fail the whole run, and retry in the next slot. Cerulean's run carried on with 59 healthy sources. That makes a block hurt less. We do not claim it prevents one.

Use another source

If an outlet publishes its own RSS, use it. In cerulean's test the publisher's feed answered 200 from the same Worker. You lose the cross-publisher query that Google News gives you. See the Google News API options.

Hosted API

Several vendors sell news APIs or hosted fetchers. Check their coverage, pricing and limits on their live pages. One example is in the last section.

Where Feedmarkdown fits

Feedmarkdown fetches Google News from its own servers, resolves redirect links to publisher URLs and scrapes each article to Markdown there. Your workflow receives an HMAC-signed webhook (X-Feedmarkdown-Signature) or pulls JSON Feed 1.1, Atom or RSS 2.0 with a Bearer key.

Your workflow never calls Google. Our fetch runs from datacenter IPs too, so we do not claim Feedmarkdown avoids this block, and we have no long-run 503 data for our own servers. If Google refuses a fetch, the source shows a red "N failed fetches" badge with the last error, and the next scheduled run tries again. A blocked redirect resolve could instead show up as fewer or empty items.

In n8n, the community node n8n-nodes-feedmarkdown is a webhook trigger that emits the payload untouched. See Google News to Slack in n8n and RSS to webhook options.

It is paid only, with a 7-day trial: Starter $19 (every 6 hours), Pro $49 (hourly), Agency $149 (every 15 minutes), as on the pricing section on 2026-11-05. Start a 7-day trial. It covers Google News and Google Alerts only, not your own feeds or publisher RSS.

What we did not test

  • n8n Cloud, Cloudflare Workers and Make. The n8n and Worker checks above were not run there.
  • Datacenter ranges beyond the Azure, AWS and OVH addresses above.
  • The relay's tunnel.
  • Whether retries or longer intervals prevent a block.
  • Residential proxy vendors.