A practical guide to using X-Robots-Tag for blocking search engine indexing of PDFs, images, and documents in Umbraco and Umbraco Cloud.
When building secure websites in Umbraco, especially those containing downloadable files like PDFs or Word documents, you may need to ensure that these assets do not get indexed by search engines like Google. This is particularly critical when dealing with private or sensitive documents that, while not password-protected, should not be publicly searchable.
This article explores the different ways to prevent indexing of media files in Umbraco, both for local/own-hosted environments and Umbraco Cloud setups. It includes working code examples, links to official documentation, and insights from Umbraco support.
Prevent search engines from indexing documents (e.g. .pdf
, .docx
, .jpg
) stored in the /media/
folder of your Umbraco site, while still allowing legitimate users to access them directly.
The recommended and most effective method is to add an HTTP response header:
X-Robots-Tag: noindex, nofollow
Google documentation: X-Robots-Tag
If you're hosting Umbraco yourself, you can intercept static file requests and apply the X-Robots-Tag
header directly using middleware.
Program.cs
):app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
var path = ctx.File.PhysicalPath;
if (!string.IsNullOrEmpty(path) &&
path.Contains("\\media\\", StringComparison.OrdinalIgnoreCase) &&
(path.EndsWith(".pdf") || path.EndsWith(".docx") || path.EndsWith(".jpg")))
{
ctx.Context.Response.Headers["X-Robots-Tag"] = "noindex, nofollow";
}
}
});
Because Umbraco Cloud serves media via Azure Blob Storage, custom middleware or standard StaticFileOptions
in Program.cs
will not affect these files.
Instead, you should use Umbraco’s built-in pipeline with a registered IConfigureOptions<StaticFileOptions>
class.
ConfigureMediaStaticFileOptions.cs
using System.IO;
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
public class ConfigureMediaStaticFileOptions : IConfigureOptions<StaticFileOptions>
{
private static readonly HashSet<string> _blockedExtensions = new(StringComparer.OrdinalIgnoreCase)
{
".pdf", ".docx", ".xlsx", ".pptx", ".jpg", ".jpeg", ".png"
};
private readonly string _backOfficePath;
public ConfigureMediaStaticFileOptions(IOptions<GlobalSettings> globalSettings, IHostingEnvironment hostingEnvironment)
{
_backOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment);
}
public void Configure(StaticFileOptions options)
{
options.OnPrepareResponse = ctx =>
{
var path = ctx.Context.Request.Path;
var ext = Path.GetExtension(ctx.File.Name);
if (path.StartsWithSegments(_backOfficePath)) return;
if (_blockedExtensions.Contains(ext))
{
ctx.Context.Response.Headers["X-Robots-Tag"] = "noindex, nofollow";
}
};
}
}
Program.cs
:builder.Services.AddTransient<IConfigureOptions<StaticFileOptions>>, ConfigureMediaStaticFileOptions>();
If you need to restrict access entirely, or serve files with permissions and logging, don’t use /media/
at all. Instead, store files in a protected folder and stream them via a controller:
[Route("private-docs/{filename}")]
public class PrivateDocsController : Controller
{
[HttpGet]
public IActionResult GetFile(string filename)
{
var path = Path.Combine("wwwroot", "private-docs", filename);
if (!System.IO.File.Exists(path)) return NotFound();
Response.Headers["X-Robots-Tag"] = "noindex, nofollow";
var mime = MimeMapping.MimeUtility.GetMimeMapping(filename);
return PhysicalFile(path, mime);
}
}
Method | Works in Own Hosting | Works in Cloud | Prevents Indexing | Blocks Access |
---|---|---|---|---|
Middleware in Program.cs |
✅ | ❌ | ✅ | ❌ |
StaticFileOptions via IConfigureOptions |
✅ | ✅ | ✅ | ❌ |
Serve via controller | ✅ | ✅ | ✅ | ✅ |
For sensitive files, combine this with:
robots.txt
exclusions/media/
The X-Robots-Tag
header is a powerful but subtle tool. When implemented correctly, especially in Umbraco Cloud, it allows you to protect your clients from accidental leakage of internal documentation while keeping their sites SEO-optimised.
If you're unsure which approach is right, start with the static header injection via IConfigureOptions
, then move to controller-based delivery for more control.
Need help with implementation or auditing your current setup? Get in touch.
Keeping your website running smoothly while you focus on your business can be overwhelming, I get it. That is where I come in. Think of me as part of your team, handling the technical stuff so you don’t have to.
Reliable support to keep your website secure and optimised
Regular updates, backups, and performance tweaks
Tailored plans designed to suit your needs
Priority care with limited availability
Please fill out the form below or contact us directly at hello@simonantony.co.uk