Skip to main content

NGINX

NGINX Remove Query Parameters: Complete Guide

by , , revisited on


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

📅 Updated: February 18, 2026 (Originally published: February 27, 2016)

This guide shows you how to use NGINX remove query parameters techniques to clean up URLs. Query strings like gclid, utm_source, and fbclid clutter URLs and hurt SEO. They also reduce cache efficiency and create a poor user experience. With tested configurations that work in production, you can strip unwanted tracking codes from your URLs.

Why NGINX Remove Query Parameters?

Marketing platforms and analytics tools append tracking parameters to URLs automatically. Here are the most common ones:

  • Google Ads: gclid, wbraid, gbraid
  • Google Analytics: utm_source, utm_medium, utm_campaign, utm_term, utm_content, _ga
  • Facebook: fbclid
  • Microsoft Ads: msclkid
  • TikTok: ttclid
  • LinkedIn: li_fat_id
  • Twitter/X: twclid
  • Pinterest: epik

These parameters serve their purpose during the initial click. However, keeping them in URLs causes several problems:

  1. Duplicate content: Search engines may index the same page multiple times. Each variation with different query strings becomes a separate URL.
  2. Cache fragmentation: Each unique URL creates a separate cache entry. This reduces hit rates significantly.
  3. Ugly URLs: Users sharing links spread tracking codes unnecessarily. The URLs look unprofessional.
  4. Log pollution: Server logs fill with redundant parameter variations. Analysis becomes harder.
  5. Privacy concerns: Tracking codes persist in browser history and bookmarks.

Using NGINX remove query parameters configurations solves all these issues with simple redirect rules.

Method 1: Strip All Query Parameters

The simplest approach removes every query parameter from incoming requests. Use this when your pages don’t require any query string functionality.

server {
    listen 80;
    server_name example.com;

    location / {
        # Redirect only if query string exists
        if ($is_args) {
            return 301 $uri;
        }

        try_files $uri $uri/ =404;
    }
}

How it works:

  • $is_args evaluates to ? when a query string exists, empty otherwise
  • $uri contains the normalized request path without query parameters
  • The 301 status code tells browsers and search engines this is a permanent redirect

Test it:

curl -I "http://example.com/page?gclid=abc&utm_source=google"
# Returns: Location: http://example.com/page

When to use this method:

  • Static marketing landing pages
  • Blog posts without comments or pagination
  • Documentation pages
  • Portfolio sites

When NOT to use this method:

  • E-commerce sites with filtering (size, color, price)
  • Search results pages
  • Paginated content (?page=2)
  • Sites using query strings for language selection

Method 2: Strip a Specific Parameter

When you need to remove only certain parameters, use the $arg_name variable. NGINX automatically creates variables for each query parameter.

server {
    listen 80;
    server_name example.com;

    location / {
        # Remove gclid parameter
        if ($arg_gclid) {
            return 301 $uri;
        }

        try_files $uri $uri/ =404;
    }
}

The $arg_gclid variable contains the value of the gclid parameter. If the parameter is absent, the variable is empty.

Multiple parameters:

You can chain multiple checks:

location / {
    if ($arg_gclid) {
        return 301 $uri;
    }
    if ($arg_fbclid) {
        return 301 $uri;
    }
    if ($arg_msclkid) {
        return 301 $uri;
    }
    try_files $uri $uri/ =404;
}

Limitation: This approach strips ALL query parameters when redirecting. It doesn’t keep other parameters. For selective removal while preserving other parameters, see Method 4.

Method 3: Strip Multiple Tracking Parameters with Map

For production deployments, the NGINX remove query parameters approach using map is most maintainable. Create a map block that detects any tracking parameter. Then trigger a redirect based on the result.

Add this to your http block in nginx.conf:

http {
    # Detect common tracking parameters
    map $args $has_tracking_params {
        default 0;
        "~*(^|&)(gclid|wbraid|gbraid|utm_source|utm_medium|utm_campaign|utm_term|utm_content|fbclid|_ga|msclkid|ttclid|twclid|epik)=" 1;
    }

    include /etc/nginx/conf.d/*.conf;
}

Then in your server block:

server {
    listen 80;
    server_name example.com;

    location / {
        if ($has_tracking_params) {
            return 301 $uri;
        }

        try_files $uri $uri/ =404;
    }
}

How the regex works:

  • (^|&) matches start of string or parameter separator
  • (gclid|utm_source|...) matches any tracking parameter name
  • = ensures we match the parameter name, not just a substring

Test it:

# With tracking param - redirects
curl -I "http://example.com/page?utm_source=google&page=2"
# Location: http://example.com/page

# Without tracking params - no redirect
curl -I "http://example.com/page?page=2&sort=name"
# Returns normal 200 response

Why use map instead of multiple if statements:

  1. Performance: Map evaluates once at request start. Multiple if blocks evaluate sequentially.
  2. Maintainability: Add or remove parameters in one place.
  3. Readability: Cleaner configuration files.

Method 4: Cache Normalization with sorted_querystring Module

Sometimes you need to preserve legitimate query parameters. The sorted_querystring module provides advanced capabilities for this use case.

dnf install nginx-module-sorted-querystring
load_module modules/ngx_http_sorted_querystring_module.so;

http {
    server {
        location / {
            # Remove tracking params, keep and sort the rest
            sorted_querystring_filter_parameter gclid fbclid utm_source 
                utm_medium utm_campaign utm_term utm_content _ga msclkid;

            proxy_pass http://backend;
            proxy_cache_key $scheme$host$uri$sorted_querystring_args;
        }
    }
}

This approach removes specified parameters from the query string. It preserves all other parameters. Then it sorts remaining parameters alphabetically. This maximizes cache hit rates.

Example behavior:

Original URL After Processing
/page?gclid=abc&color=red&size=large /page?color=red&size=large
/page?size=large&color=red /page?color=red&size=large
/page?utm_source=google /page

Choosing the Right Method

Use Case Recommended Method
Static pages, no query strings needed Method 1: Strip all
Remove one or two specific parameters Method 2: Single $arg_ check
Remove multiple tracking codes Method 3: Map-based detection
Preserve some params, remove others Method 4: sorted_querystring module
Cache normalization with parameter sorting Method 4: sorted_querystring module

Understanding $uri vs $request_uri

When configuring NGINX remove query parameters rules, understand the difference:

  • $uri: Normalized path only, no query string. Updates during rewrite processing.
  • $request_uri: Original request including query string. Never changes.

For stripping query parameters, always use $uri. This gives you the clean path without query strings.

Security Considerations

When using $uri in redirects, be aware of potential risks. The variable contains the normalized request path. NGINX normalizes dangerous sequences automatically. However, some security scanners flag this pattern.

The if condition provides protection. Redirects only happen for requests matching your location block. This mitigates injection risks.

For additional hardening:

server {
    server_tokens off;
    # ... rest of config
}

Validate your configuration with Gixy:

gixy /etc/nginx/nginx.conf

SEO Best Practices

When implementing NGINX remove query parameters for SEO:

  1. Use 301 redirects for permanent parameter removal. This tells search engines the canonical URL.
  2. Set canonical tags as a backup in your HTML: <link rel="canonical" href="...">
  3. Update Google Search Console to specify your preferred URL parameters.
  4. Monitor crawl stats after implementation. Ensure proper indexing continues.
  5. Check for redirect chains. Avoid situations where one redirect leads to another.

For comprehensive URL rewriting techniques, see our NGINX Rewrite Rules guide.

Testing Your Configuration

Always verify your changes before deploying:

# Test syntax
nginx -t

# Reload configuration
systemctl reload nginx

# Verify redirects work
curl -I "http://yoursite.com/page?gclid=test"
# Should show: HTTP/1.1 301 Moved Permanently
# Location: http://yoursite.com/page

Test edge cases:

# Multiple parameters
curl -I "http://yoursite.com/page?a=1&gclid=test&b=2"

# Encoded characters
curl -I "http://yoursite.com/page?gclid=abc%20def"

# Empty value
curl -I "http://yoursite.com/page?gclid="

# Parameter at end
curl -I "http://yoursite.com/page?other=1&gclid=test"

Performance Impact

Using NGINX remove query parameters techniques has minimal performance impact. The map directive evaluates at request start with O(1) complexity for exact matches. Regex patterns add slight overhead but remain fast.

Benchmarks show no measurable difference for typical workloads. The redirect itself adds one round trip. However, cleaner URLs improve downstream caching. The net effect is usually positive.

For high-traffic sites, consider these optimizations:

  1. Put common parameters first in regex alternation groups
  2. Use exact-match maps where possible instead of regex
  3. Monitor redirect rates to ensure they decrease over time

Common Mistakes to Avoid

Using rewrite instead of return:

# Less efficient - evaluates regex
if ($query_string ~ "gclid=") {
    rewrite ^(.*)$ $uri? permanent;
}

# Better - no regex evaluation needed
if ($arg_gclid) {
    return 301 $uri;
}

The return directive is faster. NGINX doesn’t need to evaluate a regex.

Forgetting the conditional check:

# WRONG - creates infinite redirect loop
location / {
    return 301 $uri;
}

# CORRECT - only redirect when query string exists
location / {
    if ($is_args) {
        return 301 $uri;
    }
}

Using 302 instead of 301:

# Wrong for permanent removal - 302 is temporary
return 302 $uri;

# Correct - 301 tells search engines this is permanent
return 301 $uri;

Troubleshooting

Redirect not happening:

  1. Check if NGINX reloaded: systemctl status nginx
  2. Verify location block matches: add return 200 "matched"; temporarily
  3. Check if another location takes precedence

Infinite redirect loop:

  1. Verify the if condition checks for query string presence
  2. Ensure you’re using $uri not $request_uri in the redirect target

Wrong location being matched:

  1. Remember NGINX location matching priority
  2. Prefix locations (/path) match before regex locations

Parameters still appearing in logs:

  1. Access logs capture the original request before redirect
  2. This is expected behavior

Conclusion

Using NGINX remove query parameters techniques helps you maintain clean URLs. You also improve SEO rankings and boost cache efficiency. Start with Method 1 for simple cases. Use Method 3 for production tracking parameter removal. Consider the sorted_querystring module when you need selective parameter handling.

All configurations in this guide have been tested on NGINX 1.28 running on Rocky Linux 10.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.