I just got a setup, a golang web api behind a caddy server that has HTTPS by default via Let's Encrypt, the server proxies all requests to the web api. So I went around to test my webserver "security" on sites such as securityheaders.io. They gave me an F, so I added the headers they demanded and I got an A

Access-Control-Allow-Methods "GET, POST, OPTIONS"
Strict-Transport-Security "max-age=31536000;"
Content-Security-Policy "script-src 'self'"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"

These are the headers I currently have, but I'd like to know if they are necessary for security when what I'm making is not a website but rather a API webserver, something like

Access-Control-Allow-Methods "GET, POST, OPTIONS"

So basically, all those security headers necessary if you want to just request your API?

  • Those are the decent headers for a good browser alright. Several browser's will not support them but there is a good deal of browsers that will respect that. It all depends on what you want to defend against. For example, if you want different things to be sent when accessing the API from different clients you may as well try adding something like: X-Requested-With: XMLHttpRequest. HSTS may or may not be required too. (and if you want to go overboard even HSTS pinning, although only dev versions of browsers currently support that)
    – grochmal
    Commented Jan 7, 2017 at 1:27
  • most of those are to protect html-delivered applications, APIs don't really need all that. CORS would be good for an API, but the others do basically nothing for an XMLHttpRequest and only add bandwidth.
    – dandavis
    Commented Jan 8, 2017 at 8:20
  • OWASP has a cheat sheet about API and security headers that is quite complete: cheatsheetseries.owasp.org/cheatsheets/…
    – Yves M.
    Commented Feb 26 at 9:12

1 Answer 1


Checking headers off a list is not the best technique to assert a site's security. Services like securityheaders.io can point you in the right direction but all they do is compare against a list of proposed settings without any context about your application. Consequently, some of the proposals wont't have any impact on the security of an API endpoint that serves nothing but JSON responses.

  • Strict-Transport-Security makes sense because it guarantees that users will directly connect to your site via HTTPS after their first visit and until the max-age timeout is reached - thereby preventing downgrade attacks. Even an API endpoint should be secured with SSL, so keep that header.

  • Access-Control-Allow-Methods: GET, POST, OPTIONS is not a security option per se. If your API works via CORS preflight requests you need to decide which methods you allow for cross-origin sites to use. Disabling CORS could make your API unavailable. If that particular setting is sensible depends on your implementation.

  • X-XSS-Protection: 1; mode=block can be good adivice for regular sites because it instructs the XSS Auditor (which is implemented in WebKit browsers but not Firefox) to not render the site when it detects a reflected XSS attempt. But for an API that just provides JSON responses and doesn't serve active content, this header doesn't bring any benefit.

  • X-Content-Type-Options: nosniff prevents browsers from making assumptions about the content type if the site didn't declare the type correctly. If you're running a JSON API you should serve the responses with Content-Type: application/json. If you do that correctly there will be no need to add the nosniff directive.

  • X-Frame-Options: Deny prevents any website from embedding your site in an HTML frame. That option stops clickjacking attacks where an attacker tricks users into interacting with your website through a disguised frame. But without interactive elements there is limited risk through cross-origin framing. Yet, as there are advanced attacks involving dragging content out of the frame which could disclose JSON responses, you might still want to leave that header there.

  • Content-Security-Policy headers control what kind of content from what origin your site is allowed to interact with (scripts, stylesheets, images, etc.). Your setting "script-src 'self' means that only scripts from the same origin may be loaded. A CSP is useful for regular sites but doesn't make sense for your API endpoint because you don't serve any active content that could be controlled by the CSP.

  • The Server header specifies information about the server and the software running on it. It's often advised to not send that header at all to not disclose anything about backend software and versions.

  • 3
    Also smart to remove the X-Powered-By in addition to the Server header.
    – pim
    Commented Sep 20, 2017 at 16:27
  • 6
    FWIW, Mozilla actually recommends API endpoints send a Content-Security-Policy header: observatory.mozilla.org/faq and infosec.mozilla.org/guidelines/…
    – shelley
    Commented Jun 17, 2019 at 15:57
  • @Arminius and what about the Cache-Control and Pragma headers?
    – Gawey
    Commented Aug 20, 2020 at 12:15
  • What about the Permissions Policy header that has become part of securityheaders.com checks ? Is it relevant for APIs ? I find very little documentation about it. Commented Oct 20, 2020 at 10:07
  • X-XSS-Protection is no longer recommended by OWASP neither by MDN docs Commented Aug 9, 2023 at 21:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .