HOW TO: Use Cloudflare to reverse proxy a subdirectory

October 19, 2021

What is this for?
You have a requirement to serve a complete site through a "subdirectory" (ie. /news or /blog) without being able to move it "physically" to a subdirectory on your root domain's server.

Head to the Workers page in your Cloudflare account, create a new Worker and add the following snippet into the Script box:

const LIVE_DOMAIN = ''
const SUBDIR_PATH = '/news'

// Optional additional proxy path
const ADDITIONAL_PATH = '/images'

addEventListener("fetch", event => {
    var f_url = new URL(event.request.url);
    if (f_url.pathname.startsWith(SUBDIR_PATH)||f_url.pathname.startsWith (ADDITIONAL_PATH)) {
    handleSubdir(event, f_url);
  } else {

async function handleSubdir(request) {
    var trueSourceURL = new URL(request.url);
    trueSourceURL.hostname = PROXY_FROM_DOMAIN;
    return fetch(trueSourceURL, request, { cf: { resolveOverride: LIVE_DOMAIN } })

Add the Worker to the route of your live domain (ie.*)

You'll also want to modify your home and siteurl values so they can be set by WordPress dynamically. You can do this by adding these lines in your wp-config.php (again, on the source install):

define('WP_SITEURL', 'https://' . $_SERVER['SERVER_NAME']);
define('WP_HOME', 'https://' . $_SERVER['SERVER_NAME']);

Swap the slug or "subdirectory" (in this case it's news), as well as your desired user-facing domain (in this case it's and the source domain (in this case it's https://403.NEWS.SITE.COM.

Once you click Save, your subdirectory will now serve the site from the source (visiting will show you the content from


addEventListener('fetch', event => {
  var url = new URL(event.request.url);
  if (url.pathname.startsWith('/news/') || url.pathname === '/news') {
    handleBlog(event, url);
  } else {

async function handleBlog(event, url) {
  var originUrl = url.toString().replace(

NOTE: Cloudflare allows for up to 100,000 worker requests per 24 hours and 5,000 requests per 10 minutes on a free plan. Check out their pricing after that here.