Technical Tip: How to setup HTTP health check for virtual servers
Description
Â
This article describes how to configure HTTP-based health checks for virtual servers. This allows the FortiGate to send periodic HTTP GET requests to validate that the downstream real-servers are functioning correctly.
Â
Scope
Â
FortiGate, virtual server load-balancing.
Â
Solution
Â
Before starting, it may be necessary to enable visibility in the GUI for the virtual server functionality. Navigate to System -> Feature Visibility, then select and enable Additional Features -> Load Balance.
Â

Â
Configuring the health check:
Navigate to Policy & Objects -> Health Check and select Create New.
Set the Type to HTTP, then modify the following settings as needed:
Interval:Â time between health check probes.
Timeout:Â time limit to wait for server responses to health checks.
Retry:Â number of health check attempts before the server is considered down.
Port:Â service port to send health checks to (if 0, health check inherits port from Virtual Server real-server configuration).
URL: HTTP URL for GET request health check (e.g. '/index.html' or '/test.html')
Matched content: check HTTP response and scan for the presence of this string/text.
Max redirects: maximum number of HTTP redirects allowed as part of the health check.
Select OK to save the configuration.
Â

Note: If the 'Port' setting is configured with a value of 0, the health check monitor automatically inherits the port setting from the real server and sends health check traffic to the port configured on the real server.
Applying the health check to the virtual server:
Navigate to Policy & Objects -> Virtual servers, then edit the existing virtual server (or select Create New to create a new entry).
Select the box labelled health check, then locate and select the new health check that was created in the earlier step.
Select OK to commit the change.

Â
Validating the health check results:
To check the current status of the virtual server health checks, navigate to Dashboard and then either add the Load Balance widget to an existing dashboard or add it as a Load Balance Monitor (in FortiOS v6.2 and earlier, this was instead reachable via Monitor -> Load Balance Monitor). The status of the health check will be displayed here:
Â

Â
With the example configuration in the screenshots, the FortiGate will make an HTTP GET request to the real-server address for the specified URL/path (e.g., http://<real_server_ip>/test.html) and will check if the response contains the string 'Hello'. The following is an example of what the real-server's response looks like to an end-user, as well as what the HTTP representation of the request looks like:
Â

Â
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Fri, 23 Jan 2026 01:42:26 GMT
Content-Type: text/html
Last-Modified: Fri, 23 Jan 2026 01:03:58 GMT
Transfer-Encoding: chunked
Connection: keep-alive
ETag: W/"6972c8fe-41"
Content-Encoding: gzipÂ
<!DOCTYPE html>
<html>
<body>
<p>Hello World</p>
</body>
</html>Â
<p>Hello World</p>: FortiGate health check scans and detects this content in the body of the HTTP response.
If the HTTP response does not contain any matched content, then the health check will be considered as failed/down:
Â

Â
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Fri, 23 Jan 2026 01:55:04 GMT
Content-Type: text/html
Last-Modified: Fri, 23 Jan 2026 01:53:37 GMT
Transfer-Encoding: chunked
Connection: keep-alive
ETag: W/"6972d4a1-49"
Content-Encoding: gzipÂ
<!DOCTYPE html>
<html>
<body>
<p>This is a test page</p>
</body>
</html>Â
<p>This is a test page</p>: Content does not match 'Hello' filter on health.

Â
Notes:
When configuring an HTTP health check, take care to verify that the URL path and the expected response content set on the FortiGate health check match exactly the expected response from the backend real-server. Any small differences (such as using '/index.htm' instead of 'index.html') can cause the health check to report the server as down even if it is otherwise working correctly.
When the health check result is negative, incoming traffic to the virtual server does not match the expected firewall policy, even when doing a policy match in the GUI.
Related documents:
