Security headers every small business website needs

Six HTTP security headers that close common gaps on business websites: what each does, safe starting values, and how to add them without breaking anything.

Every time someone opens a page on your website, your server sends back the page itself plus a set of HTTP headers: short instructions for the browser. A handful of these headers exist purely for security. They tell the browser to always use HTTPS, to refuse to load your site inside someone else's page, to be careful about which scripts it runs, and so on.

Security headers won't fix a vulnerable plugin or a weak password. What they do is switch on protections that modern browsers already have, and they make several common attacks harder or impossible. Most can be added in minutes.

Here are the six worth setting on almost every business website, what each one does, and a sensible starting value.

How to see your current headers

Before changing anything, see what your site sends today. In Chrome, Edge or Firefox:

  1. Open your site and press F12 to open the developer tools.
  2. Go to the Network tab and reload the page.
  3. Click the first request (your page itself) and look at Response Headers.

You can also run our free Safe Scan on Lordevo Security, which checks for these headers as part of its passive checks and lists any that are missing.

1. Strict-Transport-Security (HSTS)

What it does: tells the browser to only ever connect to your site over HTTPS, for a set period, even if someone types http:// or follows an old link. This blocks attacks that try to intercept the first, unencrypted request, for example on public Wi-Fi.

Starting value:

Strict-Transport-Security: max-age=15552000; includeSubDomains

max-age is in seconds (15552000 is 180 days). includeSubDomains applies the rule to every subdomain too.

Be careful: only add includeSubDomains if every subdomain works over HTTPS, including things like an old shop. or mail. web interface. Once a browser has seen the header, it will refuse plain HTTP for that period. You can start with a short max-age, such as one day, check that nothing breaks, then raise it.

2. Content-Security-Policy (CSP)

What it does: lists where your pages may load scripts, styles, images, fonts and frames from. If an attacker manages to inject a script into your page (cross-site scripting), the browser refuses to run it unless it comes from an allowed source. CSP is the most powerful header on this list, and the one that takes the most care.

Starting value for a simple site:

Content-Security-Policy: default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'

That allows resources from your own domain only. Most real sites also load things from elsewhere: analytics, fonts, chat widgets, payment forms, embedded videos. Each of those sources needs adding to the right directive, or it will stop working.

A safe way to roll it out: use Content-Security-Policy-Report-Only first. The browser then reports what would have been blocked (in the developer tools console) without blocking anything. Browse your important pages, note what's reported, adjust the policy, and only then switch to the enforcing header.

Many WordPress, Shopify and Wix sites rely on inline scripts added by themes and plugins. A strict CSP can be hard to achieve on those platforms, and a loose policy that allows 'unsafe-inline' scripts gives much weaker protection. Even so, a partial policy with frame-ancestors, object-src 'none' and base-uri adds value.

3. X-Content-Type-Options

What it does: stops the browser from guessing ("sniffing") what type a file is when your server has already said. Without it, a file uploaded as an image could, in some situations, be treated as a script.

Value (there is only one):

X-Content-Type-Options: nosniff

This one almost never breaks anything. Add it.

4. X-Frame-Options or frame-ancestors

What it does: controls whether other websites can load your pages inside a frame. Blocking this prevents clickjacking, where an attacker shows your page invisibly on top of theirs and tricks visitors into clicking buttons on it, such as "confirm" or "delete".

Values:

X-Frame-Options: SAMEORIGIN

or, inside your CSP:

frame-ancestors 'self'

frame-ancestors is the modern version and more flexible. Sending both is common and harmless. Use DENY / 'none' if your own site never frames its pages either. If a partner legitimately embeds your pages (a booking widget, for example), list their domain in frame-ancestors instead of blocking everything.

5. Referrer-Policy

What it does: controls how much of the current page's address is sent to other sites when a visitor clicks a link or your page loads an external resource. Full addresses can contain things you'd rather not share, like search terms, order numbers or reset tokens in query strings.

Starting value:

Referrer-Policy: strict-origin-when-cross-origin

Other sites then see only your domain (for example https://yourbusiness.com/), not the full path, and nothing at all is sent from HTTPS to plain HTTP. Your own analytics on your own domain still sees full paths. Most current browsers already use this as their default when no policy is set, but stating it explicitly keeps behaviour consistent.

6. Permissions-Policy

What it does: switches off powerful browser features your site doesn't use, such as the camera, microphone and location. If a third-party script on your page is ever compromised, it can't quietly ask visitors for those permissions.

Starting value for a typical business site:

Permissions-Policy: camera=(), microphone=(), geolocation=()

The empty brackets mean "no one may use this". If your site does use a feature, for example a store finder that asks for location, allow it for your own origin with geolocation=(self).

Headers you can skip or remove

  • X-XSS-Protection controlled a filter that modern browsers have removed. It does nothing useful now; a strong CSP is the replacement. Leaving it out is fine.
  • Server and X-Powered-By headers that announce your software and version (for example X-Powered-By: PHP/8.1) aren't security headers at all. They give attackers a head start in matching your site to known vulnerabilities. Remove or shorten them where your platform allows.

Where to add them

Where you set headers depends on how your site is hosted:

  • Behind a CDN or proxy such as Cloudflare: most let you add response headers with a rule, without touching your server.
  • Apache: Header always set lines in the site configuration or .htaccess.
  • Nginx: add_header ... always; lines in the server block.
  • WordPress: several security plugins can add headers, or your host can add them at the server level.
  • Hosted builders (Shopify, Wix, Squarespace): you often can't set all headers yourself. Check what the platform already sends. Many set some of them for you.

After any change, check the headers again in the browser's developer tools, then click through your key pages, forms and checkout to make sure everything still works.

What headers don't do

Headers are a seatbelt, not a lock. They don't patch outdated software, protect weak admin passwords or stop a vulnerable plugin from being exploited on the server. Keep your platform and plugins updated, use strong unique passwords with two-factor sign-in for admin accounts, and keep tested backups.

Headers protect visitors' browsers. If you also send email from your domain, read SPF, DKIM and DMARC explained to protect your name in people's inboxes too.

The short version

Add X-Content-Type-Options, Referrer-Policy, Permissions-Policy and frame protection today; they rarely break anything. Add HSTS once you're sure HTTPS works everywhere, starting with a short max-age. Roll out a Content-Security-Policy in report-only mode first, then enforce it once your pages run cleanly.