Classic SharePoint 404 showing pagenotfound.aspx

How to configure a custom 404 page for a SharePoint site?

4 min read.

This article explains how to use some archaic PowerShell magic to configure a custom 404 page for your Modern SharePoint Online Communication site.

If you’ve been working with SharePoint for a while, this property might be already familiar to you. A lot of settings for each site collection are stored in the root site’s property bag, and that’s where you’ll find the key “vti_filenotfoundpage” which should have the value “/sites/ContosoPublishing/Pages/PageNotFoundError.aspx”.

Classic. Like, literally, Classic SharePoint. As in “not Modern”. But hear me out – this trick might be an old one, yet it still works in 2023!

And between you and me, it better work, since the basic 404 error in classic SharePoint is pretty ugly:

It also doesn’t really give you any directions on what to do next. Even the text “go to the site home” is not a link.

And befuddlingly, with Modern Communication Sites it’s even worse (since there’s no handler for the 404 error out-of-the-box):

Well – I guess Modern SharePoint sites are still so new (they just launched, circa 2016) that it’s understandable they lack some basic functionality like this 😃

But what can we do to make the 404 experience a bit better for the end-users?


As you might be able to already guess, you can change the URL SharePoint uses for the 404 redirection! And it’ll pass a helpful URL parameter for our perusal for any custom logic, too!

This makes it possible to build something like below (apologies for the moonspeak, we Europeans are weird like that):

A custom SharePoint 404 page that reads the referring URL and offers the user helpful links.
A custom SharePoint 404 page that reads the referring URL and offers the user helpful links.

That said, though… Modern SharePoint has an extra layer of customization hindrance built-in. And that layer of extra security is called “NoScript” or “DenyAddAndCustomizePages” – a.k.a “disable custom scripting”, and it blocks a lot of things, such as modifying a web’s property bag values.

So, we’ll need to disable NoScript, add or modify the property, and then enable NoScript again. Simple as that, right?

I’ve posted about enabling custom scripts on SharePoint before, but this time we’ll build a bit of a script together!

Time needed: 10 minutes

How to change SharePoint Online to use a custom 404 page using PnP PowerShell?

  1. Upload a custom 404 page

    You’ll need to have a file you can use as the custom 404 page. This can be as simple as a small .html page you upload to the Style Library in the root site of your SharePoint tenant.

    In this file, you can even use the URL parameters SharePoint gives you to figure out what the user was looking for – but that’s beyond the scope of this article.

    I’ll just assume yours is 404.html and you’ll upload it to the root site’s Style Library.

  2. Install dependencies

    Remember to use PowerShell 7+ for this (or you’ll run into issues with some dependencies!)

    install-module pnp.powershell
    import-module pnp.powershell

  3. Define variables for your script

    We’ll define the custom 404 path and the site we’ll connect to.

    $tenant = ""
    $tenantAdmin = ""
    $custom404path = "$($tenant)/Style%20Library/404.html";

  4. Connect to your site

    Next, we’ll connect to your site. If your URLs are standard, “-TenantAdminUrl” switch shouldn’t be required.

    Connect-PnPOnline $siteUrl -Interactive -TenantAdminUrl $tenantAdmin

  5. Disable NoScript

    Now we’ll need to disable a flag (or a hidden feature) called “DenyAddAndCustomizePages” – more often nowadays called simply “NoScript”.

    Or I guess it’s been called that for the past 10 years… But still. We’ll disable that, so that we can set a custom 404 page in the next step.

    Here’s the magic command you’ll need:
    Write-Host "  Disabling NoScript" -ForegroundColor Cyan
    Set-PnPTenantSite -Identity $siteUrl -DenyAddAndCustomizePages:$false

  6. Set your custom 404 page for the site

    And now we’ll add the property bag value for the custom 404 redirection!

    Here’s how:
    Write-Host "  Adding Property Bag Key" -ForegroundColor Cyan
    Set-PnPPropertyBagValue -Key "vti_filenotfoundpage" -Value $custom404path

  7. Enable NoScript

    Now it’s time to disable custom scripting again – by enabling the “NoScript” feature! Confusing, I know…

    Here’s the commandlet:
    Write-Host "  Enabling NoScript" -ForegroundColor Cyan
    Set-PnPTenantSite -Url $siteUrl -NoScriptSite

    This is important, because you don’t want to leave your sites in less secure status if you can avoid it – and the custom scripting is not required to maintain the 404 redirection, it’s just needed to set it up!

For a copy-pasteable, longer script, scroll down the page.


This needs to be configured for each SharePoint Site Collection (or each Hub Site) separately. You could just wrap the script above in a loop and iterate over a lot of sites, like this script I yanked from Paul Bullock (see the link below and the whole script at the bottom of the page).



Copy-pasteable script snipped

You didn’t think I’d make you craft this yourself, did you? Oh I won’t – and of course, I got this from Paul Bullock anyway (see the link above) so it would be kinda pointless to make things more difficult than they need to be!

install-module pnp.powershell
import-module pnp.powershell

$tenant = ""
$tenantAdmin = ""

$sites = @(

$custom404path = "$($tenant)/Style%20Library/404.html";

foreach ($site in $sites) 
    $siteUrl = $site

    Write-Host "Setting 404 page at $($siteUrl)..."

    # Connect to SharePoint Online with PnP PowerShell library
    Connect-PnPOnline $siteUrl -Interactive -TenantAdminUrl $tenantAdmin

    # Disable NoScript
    Write-Host "  Disabling NoScript" -ForegroundColor Cyan
    Set-PnPTenantSite -Identity $siteUrl -DenyAddAndCustomizePages:$false

    # Sets the value in the property bag, 
    # note: ensure you have disabled NoScript
    Write-Host "  Adding Property Bag Key" -ForegroundColor Cyan
    Set-PnPPropertyBagValue -Key "vti_filenotfoundpage" `
        -Value $custom404path

    # Enable NoScript
    Write-Host "  Enabling NoScript" -ForegroundColor Cyan
    Set-PnPTenantSite -Url $siteUrl -NoScriptSite

    Write-Host "Script Complete! :)" -ForegroundColor Green
0 0 votes
Article Rating
Notify of

Inline Feedbacks
View all comments