How to Set Up Custom HTTP Error Pages on VergeCloud

Custom Error Pages in VergeCloud: Enhance User Experience

Default error pages work fine, but they don't look like your site. The moment a visitor hits a 503, a firewall block, or a maintenance screen, they land on a generic VergeCloud message instead of something that matches your branding. Custom Pages fixes that. You can swap in your own HTML for any of these scenarios, or just redirect to a page on your own domain.

This article covers the page types you can customize, how to set them up through the dashboard or API, and includes templates you can use right away.

Pages you can replace
  • 4xx and 5xx HTTP errors
  • Maintenance / under construction mode
  • Secure link failures
  • Firewall and WAF blocks
  • DDoS challenges (JS or CAPTCHA)
  • Rate limit pages

Each one ships with a VergeCloud default. You can keep that, upload your own HTML, or point it to a URL.

Where to set it up

Go to Panel → Custom Page. For each page type you'll see three options: default, upload HTML, or redirect.

Everything below can also be done through the API. The curl commands in this article are all API examples, for example "set a redirect via the API", so if you're configuring this from the dashboard instead, just use the upload or redirect option there and skip the curl part.

A quick gotcha worth knowing about: any image, CSS, or JS file your custom page pulls in needs to load with a 200. If a firewall rule or a geo-block happens to catch that asset, the page itself won't render right, which is annoying because that's exactly the page someone's looking at when something's already gone wrong.

Dynamic variables

VariableWhat it shows
%IP%The visitor's IP address
%SID%The server ID that handled the request
%DOMAIN%The domain that was requested
%ERRCODE%The error code shown to the visitor
%TIME%Timestamp in YYYY-MM-dd HH:mm:ss Z
%REQUEST_ID%Unique ID for the request
%CHALLENGE%Renders the DDoS challenge itself, required on challenge pages

Showing the request ID and timestamp on the page means if someone emails support about it, you can look it up in your logs right away instead of going back and forth asking what they saw.

Maintenance page

Heads up, turning this on with upload or redirect puts your whole domain into maintenance mode, not just one page.

<!DOCTYPE html>
<html>
<head>
<title>Under Construction</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Website Under Construction</h1>
  <p>%DOMAIN% is currently undergoing maintenance.</p>
  <p>Please check back later.</p>
</body>
</html>

Set this via the API (upload):
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file.html"' \
--form 'page="under_construction"' \
--form 'type="file"'

Or as a redirect via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'page="under_construction"' \
--form 'url="https://example.com/uc.html"' \
--form 'type="url"'

Server error page (500 / 502 / 503 / 504)

Shows up when your origin doesn't respond or throws one of these codes. Keep this one plain. If your origin is the thing that's broken, you don't want this page depending on anything fancy either.
<!DOCTYPE html>
<html>
<head>
<title>Server Error</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Something Went Wrong</h1>
  <p>The server was unable to process your request.</p>
  <p>Error Code: %ERRCODE%</p>
  <p>Request ID: %REQUEST_ID%</p>
  <p>Server ID: %SID%</p>
  <p>Time: %TIME%</p>
</body>
</html>

Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file.html"' \
--form 'page="error_500"' \
--form 'type="file"'

Redirect via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'page="error_500"' \
--form 'url="https://example.com/500"' \
--form 'type="url"'

DDoS challenge screens

These show up when JS or CAPTCHA verification kicks in. Don't forget %CHALLENGE% in your HTML, it's what actually loads the challenge. Leave it out and the page shows up fine, but nothing happens when someone tries to get past it.

JavaScript challenge
<!DOCTYPE html>
<html>
<head>
<title>Browser Verification</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Verifying Your Browser</h1>
  <p>Please wait while we verify your browser before accessing %DOMAIN%.</p>
  %CHALLENGE%
</body>
</html>

Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file"' \
--form 'page="ddos_js"' \
--form 'type="file"'

CAPTCHA challenge
<!DOCTYPE html>
<html>
<head>
<title>Security Verification</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Security Verification Required</h1>
  <p>Please complete the verification below to continue to %DOMAIN%.</p>
  %CHALLENGE%
</body>
</html>

Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file"' \
--form 'page="ddos_captcha"' \
--form 'type="file"'

Secure link protection means a path only works with a valid generated link, scoped by IP and time. VergeCloud splits the failure into two cases: the link expired, or the link is invalid/tampered with.

Expired

<!DOCTYPE html>
<html>
<head>
<title>Link Expired</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Secure Link Expired</h1>
  <p>This secure link has expired and can no longer be used.</p>
  <p>Request ID: %REQUEST_ID%</p>
  <p>Time: %TIME%</p>
</body>
</html>

Invalid

<!DOCTYPE html>
<html>
<head>
<title>Invalid Link</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Invalid Secure Link</h1>
  <p>The requested secure link is invalid or has been modified.</p>
  <p>Request ID: %REQUEST_ID%</p>
  <p>Time: %TIME%</p>
</body>
</html>

Both use the same page parameter, secure_link_invalid. Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file.html"' \
--form 'page="secure_link_invalid"' \
--form 'type="file"'

Or redirect via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'page="secure_link_invalid"' \
--form 'url="https://example.com/securelink"' \
--form 'type="url"'

When the firewall blocks a request

Triggered when a firewall rule blocks the request. Worth putting the IP and request ID on this page since people occasionally get blocked who shouldn't be, and having that info up front cuts down the support back and forth.
<!DOCTYPE html>
<html>
<head>
<title>Access Restricted</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Access Restricted</h1>
  <p>Your request was blocked by a firewall rule.</p>
  <p>Error Code: %ERRCODE%</p>
  <p>Request ID: %REQUEST_ID%</p>
  <p>Your IP: %IP%</p>
  <p>Time: %TIME%</p>
</body>
</html>

Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file.html"' \
--form 'page="firewall_error"' \
--form 'type="file"'

Redirect via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'page="firewall_error"' \
--form 'url="https://example.com/firewall"' \
--form 'type="url"'

When the WAF blocks a request

Same idea as the firewall page above, but this one fires specifically when the WAF catches something, not a general firewall rule. They're configured separately, so you can message them differently if you want.

<!DOCTYPE html>
<html>
<head>
<title>Request Blocked</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Request Blocked</h1>
  <p>Your request was blocked by a Web Application Firewall (WAF) rule.</p>
  <p>Error Code: %ERRCODE%</p>
  <p>Request ID: %REQUEST_ID%</p>
  <p>Your IP: %IP%</p>
  <p>Time: %TIME%</p>
</body>
</html>

Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file.html"' \
--form 'page="waf_protection"' \
--form 'type="file"'

Redirect via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'page="waf_protection"' \
--form 'url="https://example.com/waf"' \
--form 'type="url"'

When someone hits the rate limit

Shows up when someone exceeds your configured request limits. A flat 429 reads as broken, even though it's working as intended, so a quick explanation goes a long way here. This also catches normal users sometimes, usually on a shared office connection or VPN where lots of people share one IP.

<!DOCTYPE html>
<html>
<head>
<title>Too Many Requests</title>
</head>
<body style="font-family:Arial;text-align:center;padding-top:100px;">
  <h1>Too Many Requests</h1>
  <p>You have exceeded the allowed request rate.</p>
  <p>Please wait and try again later.</p>
  <p>Error Code: %ERRCODE%</p>
  <p>Request ID: %REQUEST_ID%</p>
  <p>Your IP: %IP%</p>
  <p>Time: %TIME%</p>
</body>
</html>

Redirect via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'page="rate_limit_exceeded"' \
--form 'url="https://example.com/rl"' \
--form 'type="url"'

Upload via the API:
curl --location --request GET 'https://api.vergecloud.com/v1/domains/example.com/custom-pages' \
--header 'authorization: APIKEY' \
--form 'file=@"/path/to/file.html"' \
--form 'page="rate_limit_exceeded"' \
--form 'type="file"'

Before You Enable a Custom Page

Check that every image, font, or script your page references is actually reachable publicly. Anything sitting behind a login or blocked by your own firewall rules won't load, and you'll find out the hard way when the error page itself looks broken.

If you have geo-blocking or IP restrictions running at the domain level, carve out an exception for whatever paths your custom pages pull assets from.

Test by triggering the real condition rather than just opening the file locally. Visit a path that doesn't exist to check your 404, flip on maintenance mode briefly to check that page, and so on. Opening the HTML in a browser tells you nothing about whether the variables are actually populating.

Final note

Most people never notice a custom error page until it's missing. A maintenance screen that explains itself, or a firewall block message that doesn't feel like a dead end, keeps things consistent even when something's interrupted. Server errors, maintenance, and firewall blocks are the three you'll run into most, so start there if you're not doing all of them at once.
    • Related Articles

    • Boost Web Pages Instantly with Verge Cloud

      Web Boost is designed to enhance the loading speed and overall performance of your website by optimizing static assets, images, and the delivery of code. In today’s digital landscape, speed is not just a convenience; it has a direct impact on user ...
    • How to Use a Custom SSL Certificate on VergeCloud

      Custom SSL certificates play a crucial role in securing modern applications, ensuring encrypted communication between clients and servers. VergeCloud provides a robust and user-friendly interface that allows users to upload, manage, and deploy their ...
    • Invite User

      Overview Inviting users to your VergeCloud organization is a fundamental part of managing your team and ensuring that the right individuals have access to the resources they need. VergeCloud provides a robust Member Management system that allows ...
    • Essential Steps Before Changing Nameservers to VergeCloud

      When you add a new domain to the VergeCloud User Panel, one of the first and most important tasks is confirming that your DNS settings are correct. Proper DNS management determines whether your website loads, whether email services function, and ...
    • Caching on VergeCloud: A Step-by-Step Guide to Faster Content Delivery

      Caching plays a crucial role in improving website performance by temporarily storing web content so it can be delivered faster and with less strain on your origin server. When caching is enabled through VergeCloud’s next-gen CDN, your content is ...