Skip to content

Route bots to EdgeComet with Akamai Property Manager ​

On Akamai, one Property Manager rule sends search engine and AI bot page requests to EdgeComet. The rule switches the origin to EdgeComet's render host, rewrites the path to the render endpoint and adds your render key. A child rule sends bots back to your origin when EdgeComet cannot answer.

This is the Akamai setup for prerendering or dynamic rendering, plus EdgeComet's caching and bot analytics. It works on properties that support variables, such as Ion. Visitors keep getting your site from your usual origin.

The dashboard has no Akamai guide. Take your render key and render host from the Generic Integration guide under Configuration > Connections > CDN integration.

How it works ​

The rule EdgeComet bot routing sits last under the Default Rule and matches when all of these hold:

  • The method is GET or HEAD, through the built-in variable AK_METHOD.
  • The request uses HTTPS.
  • The user agent contains a crawler token.
  • The file extension is not a static file.
  • The request has no X-Edge-Render header, which EdgeComet adds to its own requests, and no failover marker.

Its behaviors then build the request to EdgeComet:

  1. Origin Server switches to render-us.edgecomet.com on port 443, with SNI.
  2. Set Variable URL-encodes the full page URL into PMUSER_EC_URL.
  3. Modify Outgoing Request Path replaces the path with /render?url={{user.PMUSER_EC_URL}}.
  4. Modify Outgoing Request Header adds X-Render-Key from a sensitive variable.
  5. Caching: No store keeps EdgeComet's responses out of Akamai's cache. The path rewrite also changes the cache key, which keeps bot copies apart from visitor copies.

The child rule EdgeComet fail open runs Site Failover when EdgeComet times out, answers 5xx, or answers without an EC-Source header. The failover request goes back through the property to your normal origin.

Akamai adds the bot's IP address to X-Forwarded-For, which EdgeComet reads. Leave Send True Client IP Header off in this rule: EdgeComet does not read True-Client-IP.

With Tiered Distribution, or any other Akamai layer between the bot and the rule, check in Data Explorer > Bot log that bot requests show the bots' addresses, not Akamai's.

Before you start ​

  • Property Manager access with edit and activate rights on the property that serves your site.
  • A product that supports property variables, such as Ion.
  • Your Render Key and Render Host from the dashboard. If your guide shows render-de.edgecomet.com, use it in place of render-us.edgecomet.com.
  • A loop guard for the failover request. The recommended one needs your Akamai account team. See Loop guard for the failover request.

Add the rule in Property Manager ​

  1. In Control Center, open Content delivery > CDN > Properties, open the property and create a new version.
  2. Under Property Variables, click Add Variable twice. Property Manager adds the PMUSER_ prefix:
    • EC_RENDER_KEY, Initial Value your render key, security setting Sensitive.
    • EC_URL, Initial Value empty. Keep it Visible while you test, then set it to Hidden.
  3. Save the property, which makes the variables available to behaviors.
  4. Select the Default Rule, click Add Rule, choose the blank template and name it EdgeComet bot routing. Drag it to the bottom of the Default Rule's children: the last matching behavior wins.
  5. Set the criteria to Match All and add:
    • Variable: AK_METHOD is one of GET HEAD.
    • Request Protocol: HTTPS.
    • User Agent: is one of *bot* *crawl* *spider* *slurp* *WhatsApp* *Snapchat* *facebookexternalhit* *AMZN-User* *Claude-User* *Perplexity-User* *ChatGPT-User*, with Wildcards in value on and Case-sensitive value off.
    • File Extension: is not one of avif css eot gif gz ico jpeg jpg js json map mp3 mp4 ogg otf pdf png svg ttf txt wasm wav webm webmanifest webp woff woff2 xml zip, case-insensitive.
    • Request Header: X-Edge-Render does not exist.
    • Request Header: X-EC-Failover does not exist.
  6. Add the behaviors, in this order:
    • Origin Server: Origin Type Your Origin, Origin Server Hostname render-us.edgecomet.com, Forward Host Header Origin Hostname, Cache Key Hostname Incoming Host Header, Send True Client IP Header off, Verification Settings the same as the Default Rule, Use SNI TLS Extension Yes, ports 80 and 443.
    • Set Variable: Variable PMUSER_EC_URL, Create Value From Expression, {{builtin.AK_SCHEME}}://{{builtin.AK_HOST}}{{builtin.AK_URL}}, Operation URL Encode, Force Chars +.
    • Modify Outgoing Request Path: Replace the entire path with /render?url={{user.PMUSER_EC_URL}}.
    • Modify Outgoing Request Header: Modify, Other..., Custom Header Name X-Render-Key, New Header Value {{user.PMUSER_EC_RENDER_KEY}}, Avoid Duplicate Headers on.
    • Caching: No store.
    • Read Timeout: First Byte Timeout 30 seconds, above EdgeComet's 15-second render timeout.
    • Chase Redirects: off, which passes EdgeComet's redirects to the bot.
    • SureRoute: off. Its race requests fetch a test object the render host does not serve.
  7. Add the child rule from Fall back to your origin.
  8. Save, check the Errors / Warnings tab, then test on staging.

Force Chars + matters. Akamai's URL encoding leaves + as it is, and EdgeComet would read it as a space, which turns ?q=a+b into ?q=a b.

Use SNI TLS Extension is required. The render host refuses TLS connections without SNI.

Rule JSON ​

For the Property Manager API, rule format v2026-09-30. Declare the variables in the Default Rule's variables array:

json
[
  {
    "name": "PMUSER_EC_RENDER_KEY",
    "value": "YOUR_RENDER_KEY",
    "description": "EdgeComet render key sent as X-Render-Key",
    "hidden": true,
    "sensitive": true
  },
  {
    "name": "PMUSER_EC_URL",
    "value": "",
    "description": "URL-encoded original URL sent to EdgeComet",
    "hidden": false,
    "sensitive": false
  }
]

Then append this rule as the last element of the Default Rule's children:

json
{
  "name": "EdgeComet bot routing",
  "comments": "Sends crawler GET/HEAD page requests to EdgeComet. Keep this rule last under the Default Rule.",
  "criteriaMustSatisfy": "all",
  "criteria": [
    {
      "name": "matchVariable",
      "options": {
        "variableName": "AK_METHOD",
        "matchOperator": "IS_ONE_OF",
        "variableValues": ["GET", "HEAD"],
        "matchWildcard": false,
        "matchCaseSensitive": false
      }
    },
    {
      "name": "requestProtocol",
      "options": { "value": "HTTPS" }
    },
    {
      "name": "userAgent",
      "options": {
        "matchOperator": "IS_ONE_OF",
        "values": [
          "*bot*", "*crawl*", "*spider*", "*slurp*", "*WhatsApp*", "*Snapchat*",
          "*facebookexternalhit*", "*AMZN-User*", "*Claude-User*", "*Perplexity-User*", "*ChatGPT-User*"
        ],
        "matchWildcard": true,
        "matchCaseSensitive": false
      }
    },
    {
      "name": "fileExtension",
      "options": {
        "matchOperator": "IS_NOT_ONE_OF",
        "values": [
          "avif", "css", "eot", "gif", "gz", "ico", "jpeg", "jpg", "js", "json", "map", "mp3", "mp4", "ogg",
          "otf", "pdf", "png", "svg", "ttf", "txt", "wasm", "wav", "webm", "webmanifest", "webp", "woff",
          "woff2", "xml", "zip"
        ],
        "matchCaseSensitive": false
      }
    },
    {
      "name": "requestHeader",
      "options": {
        "headerName": "X-Edge-Render",
        "matchOperator": "DOES_NOT_EXIST",
        "matchWildcardName": false
      }
    },
    {
      "name": "requestHeader",
      "options": {
        "headerName": "X-EC-Failover",
        "matchOperator": "DOES_NOT_EXIST",
        "matchWildcardName": false
      }
    }
  ],
  "behaviors": [
    {
      "name": "origin",
      "options": {
        "originType": "CUSTOMER",
        "hostname": "render-us.edgecomet.com",
        "forwardHostHeader": "ORIGIN_HOSTNAME",
        "cacheKeyHostname": "REQUEST_HOST_HEADER",
        "compress": true,
        "enableTrueClientIp": false,
        "verificationMode": "PLATFORM_SETTINGS",
        "originSni": true,
        "httpPort": 80,
        "httpsPort": 443,
        "ipVersion": "IPV4"
      }
    },
    {
      "name": "setVariable",
      "options": {
        "variableName": "PMUSER_EC_URL",
        "valueSource": "EXPRESSION",
        "variableValue": "{{builtin.AK_SCHEME}}://{{builtin.AK_HOST}}{{builtin.AK_URL}}",
        "transform": "URL_ENCODE",
        "forceChars": "+"
      }
    },
    {
      "name": "rewriteUrl",
      "options": {
        "behavior": "REWRITE",
        "targetUrl": "/render?url={{user.PMUSER_EC_URL}}"
      }
    },
    {
      "name": "modifyOutgoingRequestHeader",
      "options": {
        "action": "MODIFY",
        "standardModifyHeaderName": "OTHER",
        "customHeaderName": "X-Render-Key",
        "newHeaderValue": "{{user.PMUSER_EC_RENDER_KEY}}",
        "avoidDuplicateHeaders": true
      }
    },
    {
      "name": "caching",
      "options": { "behavior": "NO_STORE" }
    },
    {
      "name": "readTimeout",
      "options": { "value": "30s", "firstByteTimeout": "30s" }
    },
    {
      "name": "chaseRedirects",
      "options": { "enabled": false }
    },
    {
      "name": "sureRoute",
      "options": { "enabled": false }
    }
  ],
  "children": [
    {
      "name": "EdgeComet fail open",
      "comments": "On timeout, 5xx, or a response without EC-Source, re-run the request against the normal origin.",
      "criteriaMustSatisfy": "any",
      "criteria": [
        {
          "name": "originTimeout",
          "options": { "matchOperator": "ORIGIN_TIMED_OUT" }
        },
        {
          "name": "matchResponseCode",
          "options": { "matchOperator": "IS_BETWEEN", "lowerBound": 500, "upperBound": 599 }
        },
        {
          "name": "responseHeader",
          "options": {
            "headerName": "EC-Source",
            "matchOperator": "DOES_NOT_EXIST",
            "matchWildcardName": false
          }
        }
      ],
      "behaviors": [
        {
          "name": "failAction",
          "options": {
            "enabled": true,
            "actionType": "RECREATED_CO",
            "contentHostname": "{{builtin.AK_HOST}}",
            "contentCustomPath": true,
            "contentPath": "{{builtin.AK_PATH}}",
            "preserveQueryString": true
          }
        }
      ]
    }
  ]
}

Set verificationMode to the mode your Default Rule's Origin Server uses. A different mode can fail the activation.

The workflow: create a property version, get its rule tree, add the variables and the rule, put the tree back, fix any errors, then activate.

If the Variable criterion does not offer AK_METHOD in your editor, make EdgeComet bot routing a Match Any parent with two Request Method criteria, GET and HEAD, and move the other criteria and the behaviors into a Match All child. Request Method takes one value per criterion.

Fall back to your origin ​

Select EdgeComet bot routing, add a Child Rule named EdgeComet fail open, and set its criteria to Match Any:

  • Origin Timeout: yes.
  • Response Status Code: is in range 500 to 599.
  • Response Header: EC-Source does not exist.

Add the Site Failover behavior: Enable on, Action Use alternate hostname in this property, Alternate Hostname in This Property {{builtin.AK_HOST}}, Modify Request Path yes with {{builtin.AK_PATH}}, Include Query String yes. The failover request uses the bot's original path and query string, not the rewritten one.

CaseBots get
EdgeComet answers with EC-Source and a status below 500, including redirects, 404 and 410EdgeComet's response
EdgeComet answers 5xxYour origin's page
EdgeComet answers without EC-Source: 401 for a wrong key, 400, a 404 for a wrong pathYour origin's page
EdgeComet does not answer in timeYour origin's page

Akamai documents Site Failover on Origin Timeout and Response Status Code. Other vendors' Akamai integrations also trigger it on a missing response header, as the third criterion does.

Test each case on staging before you activate on production. See Test the fallback.

Loop guard for the failover request ​

The failover request passes through the property again, and it would match EdgeComet bot routing once more. The X-EC-Failover criterion stops that, once the failover request carries the header.

Akamai Professional Services adds the header to Site Failover through an Advanced behavior, which only Akamai can configure. Ask your Akamai account team to add this to EdgeComet fail open:

xml
<forward:availability.fail-action2>
  <add-header>
    <status>on</status>
    <name>X-EC-Failover</name>
    <value>1</value>
  </add-header>
</forward:availability.fail-action2>

Without access to Akamai Professional Services, use a failover hostname instead:

  1. Under Property Hostnames, add a hostname such as ec-failover.example.com on the property's existing edge hostname. It needs no DNS record.
  2. In EdgeComet bot routing, replace the X-EC-Failover criterion with Hostname is not one of ec-failover.example.com.
  3. In Site Failover, set Alternate Hostname in This Property to ec-failover.example.com.
  4. Set the Default Rule's Forward Host Header to a Custom Value with your main hostname. Otherwise your origin receives Host: ec-failover.example.com on failover.

The failover hostname suits a property that serves one hostname. A property with several hostnames needs one failover hostname for each.

Test on staging ​

  1. On the Activate tab, click Activate v# on Staging. Akamai says staging activation usually takes under 3 minutes.
  2. Resolve the staging edge hostname, with -staging before the final .net, and use its address with curl --resolve:
bash
dig +short www.example.com.edgekey-staging.net

H=www.example.com; IP=STAGING_IP
GB="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

# Bot page: expect ec-source and x-akamai-staging
curl -sS -D - -o /dev/null --resolve $H:443:$IP -A "$GB" "https://$H/"

# Browser: expect no ec- headers
curl -sS -D - -o /dev/null --resolve $H:443:$IP -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" "https://$H/"

# Static file and loop guard: expect no ec-source
curl -sS -D - -o /dev/null --resolve $H:443:$IP -A "$GB" "https://$H/favicon.ico"
curl -sS -D - -o /dev/null --resolve $H:443:$IP -A "$GB" -H "X-Edge-Render: test" "https://$H/"

Staging servers change over time. Resolve the address again before each round of tests.

To check the encoded URL, send an Enhanced Debug header, Akamai-Debug: YOUR_TOKEN vars, and look for PMUSER_EC_URL with %3F, %26 and %2B in it.

Test the fallback ​

  • A missing EC-Source: set PMUSER_EC_RENDER_KEY to a wrong value on a staging version. EdgeComet answers 401 without EC-Source, and bots must get your origin page without EC- headers.
  • A failed connection: add this staging-only child rule to EdgeComet bot routing, above EdgeComet fail open, and send a crawler request with the header X-EC-Test-Failover: YOUR_TEST_SECRET. Bots must get your origin page.
json
{
  "name": "EdgeComet failover test (staging only)",
  "criteriaMustSatisfy": "all",
  "criteria": [
    {
      "name": "contentDeliveryNetwork",
      "options": { "matchOperator": "IS", "network": "STAGING" }
    },
    {
      "name": "requestHeader",
      "options": {
        "headerName": "X-EC-Test-Failover",
        "matchOperator": "IS_ONE_OF",
        "values": ["YOUR_TEST_SECRET"],
        "matchWildcardName": false,
        "matchWildcardValue": false,
        "matchCaseSensitiveValue": true
      }
    }
  ],
  "behaviors": [
    { "name": "breakConnection", "options": { "enabled": true } }
  ]
}

The rule matches only on the staging network.

Activate on production ​

Click Activate v# on Production, which Akamai says usually takes under 4 minutes, and run Verify install in the dashboard guide. To roll back, activate the previous version.

Let EdgeComet through Akamai security ​

EdgeComet's own requests to your site carry X-Render-Key and X-Edge-Render, which sends them past this rule to your origin. App & API Protector and Bot Manager see them first.

Add exceptions on the request header X-Render-Key with your exact key. See Akamai App & API Protector and Bot Manager.

Check the integration ​

After the production activation, run Test connection and Verify install in the Generic Integration guide, then see Check that search and AI bots reach EdgeComet.

Update or remove ​

After a render key rotation, update PMUSER_EC_RENDER_KEY and the security exceptions, then activate. To remove EdgeComet, delete the rule or activate a version without it.

If it does not work ​

Bots get your origin page without EC-Source ​

The rule did not match, or the fallback ran. Check that each user agent token has wildcards on both sides, the path is not a static file, the rule is last under the Default Rule and the request uses HTTPS. To see EdgeComet's own answer, turn off EdgeComet fail open on a staging version.

401 Authentication failed: invalid render key or domain mismatch ​

PMUSER_EC_RENDER_KEY is wrong, or the host in the URL is not one of your website's domains. www and the root domain count as different domains.

400 Invalid URL ​

The url parameter is missing or damaged. Check PMUSER_EC_URL with the vars debug option, and look for a behavior in a parent rule that removes query parameters.

A plain 404 Not Found without EC-Source ​

The path EdgeComet received is not /render. An Origin Base Path in a parent rule adds a prefix, and other behaviors cannot override it.

Bots get a 301 to render-us.edgecomet.com ​

The request reached the render host over plain HTTP, which redirects to HTTPS. Keep the Request Protocol: HTTPS criterion, and keep Chase Redirects off.

TLS errors to the render host ​

Set Use SNI TLS Extension to Yes.

Activation fails after you add the rule ​

Use the same Verification Settings in the rule's Origin Server as in the Default Rule.

Failover loops or errors ​

The loop guard is missing: the Advanced behavior is not in place yet, or the failover hostname is not excluded.

Test connection fails ​

App & API Protector or Bot Manager blocks EdgeComet's requests. Add the exceptions. See Let EdgeComet through Akamai security.