How to Enable HTTP/2 in Apache and Nginx
Enable HTTP/2 on Apache or Nginx, validate and reload safely, then verify that your site actually negotiated the protocol.

To enable HTTP/2 for a browser-facing site, configure it on the HTTPS virtual host or server block, make sure the server build includes its HTTP/2 module, and confirm that TLS negotiation supports ALPN. In Apache, load mod_http2 and set Protocols h2 http/1.1. In Nginx, enable ngx_http_v2_module and use http2 on; alongside the TLS listener. Test the configuration before reloading, then inspect a real connection: a successful syntax check alone does not prove HTTP/2 was negotiated.
This guide covers both servers, safe rollout, verification, common failures, and operational tradeoffs. The directives apply to current configurations described by the projects’ documentation; check the documentation that matches your installed version and package.
1. Check prerequisites before changing configuration
HTTP/2 support has two parts: the server must have the relevant module available, and the connection must negotiate the protocol. For normal public websites, configure HTTP/2 over HTTPS. Browsers generally use HTTP/2 on HTTPS connections, and TLS ALPN lets the client and server agree on the protocol during the TLS handshake. A working certificate and HTTPS setup are prerequisites; enabling a directive does not create or repair HTTPS.

| Server | Module | Configuration directive | Negotiation signal |
|---|---|---|---|
| Apache httpd | mod_http2 |
Protocols h2 http/1.1 |
Client protocol; Apache HTTP2 environment flag |
| Nginx | ngx_http_v2_module |
http2 on; |
Client protocol; Nginx $http2 variable |
Before editing, identify the exact virtual host or server block that serves the hostname, and confirm that HTTPS already works there. Back up or version-control the configuration. Package names, config paths, service names, and module packaging vary by operating system, so use the commands and paths provided by your host.
Apache module availability
Apache’s HTTP/2 implementation is mod_http2. The module documentation lists compatibility from httpd 2.4.17. A distribution may package and enable the module separately. For a source build, the Apache guide says the build requires libnghttp2 (at least 1.2.1) and the --enable-http2 configure option. Check the installed build before considering a rebuild.
If the module is available but not loaded, load it using the path appropriate to the installation:
LoadModule http2_module modules/mod_http2.so
Some packages manage module loading through their own enablement tools or include files. Avoid adding a duplicate LoadModule line if the module is already loaded.
Nginx module availability
Nginx uses ngx_http_v2_module. The official reference says the module is not built by default in source builds and is enabled with --with-http_v2_module. Packaged builds may already include it. Inspect the installed build and package before planning a rebuild; do not assume that every binary was compiled with the same modules.
2. Enable HTTP/2 in Apache
Put the Protocols directive in the HTTPS virtual host to limit its scope to that hostname. Apache also permits it at server scope, which affects a broader configuration. List h2 first because Apache treats the leftmost protocol as most preferred. Keep http/1.1 in the list so clients that do not negotiate HTTP/2 can fall back.
<VirtualHost *:443>
ServerName example.com
Protocols h2 http/1.1
# Keep the site's existing TLS configuration here.
SSLEngine on
SSLCertificateFile /path/to/your/certificate.pem
SSLCertificateKeyFile /path/to/your/private-key.pem
</VirtualHost>
Replace the hostname and certificate paths with the values already used by the site. Do not copy the example TLS lines over a working setup without checking the distribution’s configuration. The essential HTTP/2 setting is Protocols h2 http/1.1 in the TLS virtual host.
TLS and cipher compatibility
Apache’s guide says the SSL library must support ALPN for browser-facing HTTP/2; it names OpenSSL 1.0.2 as a minimum in its compatibility guidance. Treat that version detail as historical guidance, and check the actual versions in your deployment. The guide also warns that an unsuitable cipher suite can lead browsers to refuse HTTP/2 and fall back to HTTP/1.1. If HTTPS works but HTTP/2 does not, check the TLS stack and cipher configuration rather than repeatedly changing the protocol directive.
Cleartext HTTP/2 is a separate case
Apache supports cleartext HTTP/2 using h2c, for example Protocols h2 h2c http/1.1. This is distinct from HTTP/2 over TLS, which uses h2. Apache’s guide notes that h2c has been removed from the current specification, so it is not the normal setup for browser-facing websites. Enable it only when you have a specific cleartext use case and understand the clients and network path involved.
3. Enable HTTP/2 in Nginx
In the server block for the HTTPS hostname, keep the TLS listener and HTTP/2 setting as separate directives. The current Nginx reference uses listen 443 ssl; with http2 on;:
server {
listen 443 ssl;
server_name example.com;
http2 on;
ssl_certificate /path/to/your/certificate.pem;
ssl_certificate_key /path/to/your/private-key.pem;
# Keep the site's existing root, proxy, and location settings here.
}
Use the actual certificate and key paths, and preserve the rest of the site’s existing server block. The TLS connection needs ALPN support for HTTP/2. The Nginx reference documents ALPN with OpenSSL 1.0.2 and later. Check the versions in your installed build and follow the matching Nginx documentation if your release does not accept http2 on;. Older tutorials may show different syntax; do not assume an old directive form is valid for your installed release.
4. Validate, reload, and verify negotiation
- Confirm the target block. Check that the hostname resolves to the server and that the virtual host or server block you changed is the one serving its HTTPS traffic.
- Run the syntax check. Use the command for your installation and resolve every reported error before reloading.
- Reload through the service manager. Use the service name and reload procedure for the host. A reload applies accepted configuration without treating a syntax test as proof of protocol negotiation.
- Make a fresh HTTPS request and inspect the negotiated protocol. Use a client that supports HTTP/2. For example, if your curl build supports it, request HTTP/2 and print the reported HTTP version:
curl --http2 -sS -o /dev/null -w 'HTTP version: %{http_version}\n' https://example.com/
A result of 2 indicates that curl used HTTP/2 for the request. If curl reports 1.1, that can mean negotiation fell back; it does not by itself identify why. Check that curl was built with HTTP/2 support and test the public hostname over HTTPS.
Configuration checks and server-side signals
For Apache, run:
apachectl configtest
Apache’s HTTP2 environment flag can be used by server-side configuration or application logic as a signal that the request uses HTTP/2. Consult the module reference for the supported context and behavior before relying on it in logs or application code.
For Nginx, run:
nginx -t
Nginx exposes $http2, which identifies the negotiated protocol: the reference documents h2 for HTTP/2 over TLS and h2c for cleartext. You can temporarily include the variable in an access log format to observe requests, then remove or retain the logging change according to your operational needs.
For example, a temporary Nginx log format can include the protocol field:
log_format with_http2 '$remote_addr $host "$request" $status protocol=$http2';
access_log /var/log/nginx/access.log with_http2;
Check the log after making a fresh request. A syntax check only establishes that the configuration parses; a request observed by the client or server is needed to establish what was negotiated.
5. Troubleshooting: why a site still uses HTTP/1.1
| Symptom | Likely cause | What to check or fix |
|---|---|---|
| Configuration test reports an unknown directive | The module is missing, not loaded, or the installed release uses different syntax. | Inspect the actual server build and package. For Nginx, verify ngx_http_v2_module and consult the version-matched reference. For Apache, verify mod_http2 is available and loaded. |
| Configuration test passes, but the client reports HTTP/1.1 | The request may hit another virtual host/server block, use a client without HTTP/2 support, or fail HTTP/2 negotiation. | Check hostname routing, the HTTPS block, client support, ALPN, and server-side protocol signals. |
| HTTPS works but browsers fall back | TLS ALPN support may be absent, or Apache’s TLS cipher configuration may not be acceptable for HTTP/2. | Inspect the deployed TLS library and settings. Apache specifically documents fallback when the cipher setup is unsuitable. |
| HTTP/2 works on one hostname but not another | The hostname may use a different TLS virtual host, server block, proxy, or load balancer. | Trace the request path and configure the endpoint that terminates TLS for that hostname. Verify each hostname separately. |
| Reload fails or the server keeps the old behavior | There may be a syntax error, a reload sent to the wrong service, or a different config file is active. | Read the test and service-manager output, confirm the loaded configuration path, fix errors, and repeat the test before reloading. |
| curl does not show HTTP/2 | The curl binary may lack HTTP/2 support, or the server negotiated a fallback. | Check curl’s build features, use a client that supports HTTP/2, and compare client output with server-side signals. |
When diagnosing, change one cause at a time and repeat the request. This makes it easier to distinguish a module or syntax problem from hostname routing or TLS negotiation.
6. Performance, reliability, and operational notes
HTTP/2 allows multiple streams over one TCP connection and does not change HTTP request/response semantics. It does not guarantee that every site or workload will become faster. The outcome depends on the application, network, TLS, server behavior, and the client’s requests. Measure the pages and traffic patterns that matter to your site rather than assuming that enabling the protocol produces a particular speed improvement.
Apache notes that HTTP/2 can increase resource consumption because it starts additional worker threads for HTTP/2 processing. Consider available capacity on busy hosts, and monitor the server after rollout. For either server, keep an eye on error rates, resource use, and the protocol actually negotiated across the hostnames you intended to change.
HTTP/2 support does not remove the value of a compatible fallback. Apache’s Protocols h2 http/1.1 expresses preference for HTTP/2 while retaining HTTP/1.1 for clients that need it. Nginx negotiates a protocol with the client; do not infer that every request will use HTTP/2 simply because the module is enabled.
Apache’s guide says Server Push is deprecated and points readers toward Early Hints as an alternative. Enabling HTTP/2 does not require enabling Push; avoid treating it as a recommended part of a new setup.
7. Capture a page screenshot without setting up a browser
After configuring a site, you may need screenshots for a release note, visual review, or documentation. You can capture pages with a browser automation setup, or use ScreenshotNeo, a website screenshot API and MCP server for developers. Its API accepts one GET request with a URL and can return an image or PDF. See the ScreenshotNeo API documentation for request options.

cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
These examples save the response as WebP. Use your API key in place of YOUR_API_KEY, and consult the docs for output and capture parameters. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each of those cleanup steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed as clean shots, and responses include X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients.
Or skip the browser setup
Make one GET request with a URL. For example:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, no card required.
8. Frequently asked questions
Does HTTP/2 require changing application code?
Enabling the protocol is a server and connection configuration task. HTTP/2 does not change HTTP request/response semantics, though application and server behavior still affect performance.
Should I enable HTTP/2 on port 80?
For ordinary browser-facing sites, configure HTTP/2 over HTTPS. Apache’s h2c mode is a distinct cleartext case and is not the normal browser setup.
How can I tell whether HTTP/2 is active for a specific hostname?
Make a fresh HTTPS request to that hostname using an HTTP/2-capable client and inspect the negotiated version. You can also use Apache’s HTTP2 environment flag or Nginx’s $http2 variable as server-side signals.
Do I need to turn on Server Push?
No. It is not required to enable HTTP/2, and Apache’s guide describes Server Push as deprecated.
Primary references
- Apache HTTP Server: HTTP/2 guide — protocol selection, build requirements, TLS/ALPN, and h2c.
- Apache HTTP Server: mod_http2 reference — module configuration, environment flag, and resource considerations.
- Nginx: ngx_http_v2_module reference — build option, current configuration example, ALPN, and negotiated-protocol variable.


