403 Cloudflare Error When Calling My Render API from Vercel (Server Actions)

Hi everyone :waving_hand:

I’m hosting a NestJS API on Render, and I have both:

  • the default .onrender.com subdomain
  • and a custom domain connected to that service.

My frontend is hosted on Vercel, and I’m using Server Actions to make requests from the frontend to the Render API.

The problem: whenever a Server Action tries to call the API (regardless of whether I use the .onrender.com subdomain or the custom domain), I receive a 403 Forbidden response — the full Cloudflare “Access Denied” HTML page is returned.

:white_check_mark: What I’ve tried:

  • Adding a custom User-Agent (e.g., “MyApp Frontend”).
  • Setting Content-Type: application/json.
  • Testing with both GET and POST requests.
  • Verified that the exact same requests work perfectly from Postman or from localhost.

This only fails when the request originates from Vercel’s backend/server environment (Server Actions or API routes).

I’m not using Cloudflare on my end, so I believe Render is applying Cloudflare protection automatically behind the scenes, even when using a custom domain.

:red_question_mark: My questions:

  • Is there a way to disable or adjust this protection for my service to allow trusted requests from Vercel?
  • Can I whitelist a particular origin, IP range, or User-Agent?
  • Is this behavior expected when calling Render from other server-side environments?

Any help or guidance would be appreciated :folded_hands:
Happy to provide extra details (error payload, headers, etc.) if needed.

2 Likes

Im seeing the same. When calling endpoints on my render server i get this often:

<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
<head>
<title>Attention Required! | Cloudflare</title>
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
<style>body{margin:0;padding:0}</style>


<!--[if gte IE 10]><!-->
<script>
  if (!navigator.cookieEnabled) {
    window.addEventListener('DOMContentLoaded', function () {
      var cookieEl = document.getElementById('cookie-alert');
      cookieEl.style.display = 'block';
    })
  }
</script>
<!--<![endif]-->


</head>
<body>
  <div id="cf-wrapper">
    <div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
    <div id="cf-error-details" class="cf-error-details-wrapper">
      <div class="cf-wrapper cf-header cf-error-overview">
        <h1 data-translate="block_headline">Sorry, you have been blocked</h1>
        <h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> onrender.com</h2>
      </div><!-- /.header -->

      <div class="cf-section cf-highlight">
        <div class="cf-wrapper">
          <div class="cf-screenshot-container cf-screenshot-full">
            
              <span class="cf-no-screenshot error"></span>
            
          </div>
        </div>
      </div><!-- /.captcha-container -->

      <div class="cf-section cf-wrapper">
        <div class="cf-columns two">
          <div class="cf-column">
            <h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>

            <p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
          </div>

          <div class="cf-column">
            <h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>

            <p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
          </div>
        </div>
      </div><!-- /.section -->

      <div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
  <p class="text-13">
    <span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">92487712aa0e7c3b</strong></span>
    <span class="cf-footer-separator sm:hidden">&bull;</span>
    <span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
      Your IP:
      <button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
      <span class="hidden" id="cf-footer-ip">98.42.137.19</span>
      <span class="cf-footer-separator sm:hidden">&bull;</span>
    </span>
    <span class="cf-footer-item sm:block sm:mb-1"><span>Performance &amp; security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
    
  </p>
  <script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
</div><!-- /.error-footer -->


    </div><!-- /#cf-error-details -->
  </div><!-- /#cf-wrapper -->

  <script>
  window._cf_translation = {};
  
  
</script>

</body>
</html>

Hi folks, we’re taking a look. It seems related to Cloudflare protections for Authorization Bypass in Next.js Middleware · CVE-2025-29927 · GitHub Advisory Database · GitHub

1 Like

It appears Cloudflare enabled this rule for customers unilaterally: New Managed WAF rule for Next.js CVE-2025-29927. | Cloudflare Docs.

They have since rolled it back, and no more requests are being blocked. Make sure to update your Next.js version to the patch release to prevent the security vulnerability from being exploited.

1 Like

updating next.js does not seem to work for me, as i have a similar issue (fetching a render hosted API on a next.js vercel environment, specifically in a server component), and it still crashes. the logs recieve unexpected html instead of the expected json i would normally get.

also worth noting that fetching client-side does not give any errors. only server-side requests fail

@m4c1elz: This issue was resolved on Saturday morning. If this is still happening, would you mind getting in touch at support@render.com with details?