How do I add user agent and response fields to NGINX logs?

The Citead team, updated

In short. Define a named log_format with request and response variables, select it in access_log, test the configuration and reload NGINX.

Definition: An NGINX access log records requests using variables selected in a named log_format template. The access_log directive selects the destination and template; $http_user_agent records the request's User-Agent header and $status records the response status.

Key facts

  • As of 17 October 2026, NGINX's request logging documentation places log_format in the http context and permits access_log in http, server and location contexts, among others.
  • NGINX's core HTTP variables expose request headers through $http_name and response headers through $sent_http_name, with lowercase names and underscores replacing dashes.
  • NGINX's command-line reference documents nginx -t for checking configuration syntax and opening referenced files.
  • NGINX's Beginner's Guide states that configuration changes take effect after a reload or restart.

Which variables record the request and response?

NGINX's logging module documentation shows that the predefined combined format already includes $http_user_agent, $status and $body_bytes_sent. A custom format adds fields such as $request_time and response headers.

VariableRecorded value
$remote_addrClient address.
$time_iso8601Local time in ISO 8601 format.
$requestFull original request line.
$http_user_agentUser-Agent request header.
$statusResponse status.
$body_bytes_sentBytes sent to the client, excluding response headers.
$request_timeRequest processing time in seconds, with millisecond resolution.
$sent_http_content_typeContent-Type response header.

The core HTTP module reference defines the header naming rules used for $http_user_agent and $sent_http_content_type. The logging documentation defines $request_time from the first bytes read from the client to the log write after the last bytes are sent to the client.

Where does the configuration go?

NGINX's logging reference defines the format name as the link between log_format and access_log. The following example adapts its documented syntax. These directives belong inside the existing http block; the path follows the documentation's example log destination.

log_format bot_fields escape=json
    '{"time":"$time_iso8601",'
    '"client":"$remote_addr",'
    '"request":"$request",'
    '"user_agent":"$http_user_agent",'
    '"status":"$status",'
    '"body_bytes":"$body_bytes_sent",'
    '"request_time":"$request_time",'
    '"content_type":"$sent_http_content_type"}';

access_log /spool/logs/nginx-access.log bot_fields;

The custom name bot_fields selects this template. The format quotes every value, so status, byte count and timing are JSON strings. The documented escape=json setting escapes quotation marks, backslashes and control characters inside variable values.

The access_log directive can alternatively sit in the relevant server or location block. Several logs can be configured at the same configuration level. Omitting the format name selects combined.

How is the change checked and applied?

The command-line reference defines the configuration test:

nginx -t

After a successful test, the reload command documented in NGINX's Beginner's Guide applies the edited configuration:

nginx -s reload

During reload, the master process checks the new configuration and starts new worker processes if it succeeds. Old workers finish serving their current requests before exiting. If applying the configuration fails, NGINX continues with the old configuration.

FAQ

Why does a missing header appear as a hyphen?

NGINX's logging documentation specifies a hyphen when a variable value is unavailable. In the JSON example, the surrounding quotes make that value the string "-".

Why might a request be absent from the log?

The same documentation specifies that access_log off cancels logging directives at its configuration level, and an if condition suppresses logging when it evaluates to zero or an empty string. Requests are logged in the location where processing ends, which can change after an internal redirect.

Sources

  1. NGINX, "Module ngx_http_log_module", undated
  2. NGINX, "Module ngx_http_core_module", undated
  3. NGINX, "Command-line parameters", undated
  4. NGINX, "Beginner's Guide", undated

Check how a page reads to answer engines. Open the GEO score analyzer

Test a page and see what to fix first

The analysis usually takes less than 10 seconds and needs no account.

400,000+ pages scored in the public benchmark