Cloudflare Shadowed DNS Records: Find the Ones That Do Nothing
Cloudflare now flags shadowed DNS records: entries under a delegated subdomain that it never serves. Find them, confirm with dig, and clean up safely.
The short answer
A shadowed DNS record in Cloudflare sits at or below a subdomain delegated with an NS record, so Cloudflare keeps it but does not answer queries with it. Find them on the DNS Records page or with the API flag include_shadow_metadata=true, confirm with dig, then move the record to the delegated nameservers, delete the leftover, or remove the delegation after checking every record. Keep live glue records, because they are still served.

Reading options
On this page
A shadowed DNS record in Cloudflare is a record that sits under a subdomain you have handed to other nameservers with an NS record. It still shows in your list, but Cloudflare will not answer DNS queries with it, so editing it changes nothing on the internet. The fix is to decide which side should own that name: move the record to the delegated nameservers, delete the leftover copy, or remove the delegation itself.
Since 14 September 2026, Cloudflare shows shadowed record warnings for all zones, and its changelog says the record "remains present, but your zone is not authoritative for it". In plain words: some records in your zone may have done nothing for months, and adding them never gave you an error.
By the end of this guide you will be able to find every shadowed record in a zone, see which delegation hides it, confirm the real answer with dig, and clean it up without taking a subdomain offline.
What a shadowed record actually is
First, two terms. A zone is the set of DNS records for your domain that Cloudflare answers for. A subdomain delegation is an NS record on a name like sub.example.com that says "for this name and everything under it, ask these other nameservers instead".
Cloudflare's reference page puts it simply: any record you keep "at or below" a delegation point is shadowed. It stays stored in your zone, but authority for that name now belongs to the delegated nameservers.
Think of a building's front desk. If the owner of floor 5 says "send all floor 5 visitors to my own office", any note the desk keeps about flat 5B is useless. The desk just points visitors upstairs. Your shadowed record is that note.
Cloudflare's docs say shadowed records appear in exactly two ways:
- You added a delegation over records that already existed, for example you pointed a subdomain at an outside provider and left the old records in place.
- You added records under a name that was already delegated, expecting them to work from the parent zone.
Why this matters: in neither case does Cloudflare return an error, which is why the warnings and API metadata exist.
The one exception: glue records
A glue record is an A or AAAA record that tells resolvers the IP address of a nameserver which lives inside the subdomain it serves. Without it, a resolver would go in a circle: to find sub.example.com it needs ns1.sub.example.com, and to find that it needs sub.example.com.
Glue is shadowed by definition, but Cloudflare still serves it in the additional section of the referral response, so resolvers can get started. A shadowed glue record is normal; keep it.
This example zone combines the examples from Cloudflare's reference page to show all three kinds of record. The addresses are documentation placeholders:
sub.example.com NS ns1.sub.example.com.
ns1.sub.example.com A 192.0.2.1
www.sub.example.com A 192.0.2.2In this zone, the NS record creates the delegation, the ns1 record is live glue, and the www record is a normal shadowed record that Cloudflare will not serve.
Before you start
Gather this first:
- Access: a Cloudflare login with permission to view and edit DNS for the zone.
- A zone on a full setup: Cloudflare's delegation guide says DNS delegation is not possible for domains using a CNAME (partial) setup, so this guide applies to zones where Cloudflare is your authoritative DNS.
- An API token (optional but useful): a token with
Zone DNS Readfor the zone is enough to list and export records. This guide makes its changes in the dashboard, so read access is all the token needs. - Tools: a terminal with
curl,digandjqinstalled. - The other side: a login, or at least a contact, for whoever runs the delegated nameservers. You cannot see their records from Cloudflare.
- A backup: a fresh export of the zone file. We do this in Step 1.
- Time: about 30 minutes for a small zone.
- Risk level: reading is zero risk. Deleting a shadowed non-glue record is low risk. Deleting an
NSdelegation is high risk, because it can take a whole subdomain offline.
Quick tip: if a subdomain might point at something you no longer control, that is a different problem, covered in how to find and clean up dangling DNS records.
Find and fix shadowed records
Step 1: Export the zone as a backup
Before you touch anything, take a copy of every record. If a delete goes wrong, you will have the exact values to put back.
In the Cloudflare dashboard, select your domain and go to the DNS Records page, select Import and Export, then select Export. Save the file somewhere safe and name it with today's date.
You should get a plain text zone file, one record per line. Check that it is not empty. Cloudflare also offers the same export through the API at /zones/{zone_id}/dns_records/export if you script your backups.
Heads up: Cloudflare adds tags like cf-proxied:true to each line in the export. Keep them. If you ever re-import a record, that tag decides whether it comes back proxied.
Step 2: Look at the warnings in the dashboard
In the Cloudflare dashboard, select your domain and open its DNS section to look for shadowed record warnings. Cloudflare's changelog says these warnings now appear for all zones, but its docs do not say exactly where on the page they show, so use the API in Step 3 as the reliable check.
For each warning, note the record name, type and content. Then find the NS record at a parent name: for www.sub.example.com, that is an NS record named sub. That record is the delegation doing the shadowing.
Step 3: Pull the full list with the API
For a bigger zone, ask the API for shadow metadata: extra fields Cloudflare adds to each record's meta object, only when you request them.
First, create a token. In the dashboard go to My Profile > API Tokens, select Create Token, and give it Zone DNS Read for this one zone. Cloudflare's docs warn that the token secret is "only shown once", and that you should not store it in plaintext where others can access it.
Next, this sets two shell variables for your current terminal session. Replace both placeholder values with your own zone ID and token, and never paste a real token into a chat, a ticket or a shared document:
export ZONE_ID="your-zone-id-here"
export CLOUDFLARE_API_TOKEN="paste-your-token-here"This command lists the zone's records with shadow metadata turned on. It asks for 100 records per page, because Cloudflare only computes the metadata for pages of 1,000 records or fewer:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?include_shadow_metadata=true&per_page=100" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"Shadowed records carry a shadowed_by field. If total_pages in the result_info block is more than 1, repeat the request with &page=2 and so on.
This version pipes the same response through jq and prints only the shadowed records, one per line, with their glue flags:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?include_shadow_metadata=true&per_page=100" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
| jq -r '.result[] | select(.meta.shadowed_by != null) | "\(.type) \(.name) \(.content) glue=\(.meta.is_glue // false) dead_glue=\(.meta.dead_glue // false)"'For the example zone, you would see two lines: the ns1.sub.example.com record with glue=true, and the www.sub.example.com record with glue=false.
Step 4: Understand the four metadata fields
Cloudflare's reference page defines them like this:
shadowed_by: a list of the IDs of theNSrecords that hide this record. Apex records, the ones named exactlyexample.com, never carry it.is_glue: set totrueon anAorAAAArecord whose name matches the target of a delegatingNSrecord. This is required glue, and it is still served.dead_glue: set totrueon glue that is never served, because a shallower delegation, one closer toexample.com, takes authority first. It always comes withis_glue: true.shadowed_records_count: appears on the delegatingNSrecord itself and says how many records it hides. It is capped at 10,000, so 10,000 means "at least 10,000".
Step 5: Narrow it down by delegation or by record
This first command lists every record hidden by one delegation, here sub.example.com. It needs include_shadow_metadata=true, and Cloudflare's docs say it returns an error without it:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?include_shadow_metadata=true&shadowed_by_name=sub.example.com" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"This second command works the other way round. Give it one record name and it returns the NS delegations that shadow it, checking the name itself and each parent name except the apex. It does not need the metadata flag:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?shadowing_name=www.sub.example.com" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"The value you pass to either filter must be a subdomain, not example.com itself.
Step 6: Confirm what the internet really sees
The API shows what is stored; dig shows what resolvers get back. Do this before you change anything.
This first command finds the Cloudflare nameservers for your domain and saves the first one in a variable:
CF_NS=$(dig NS example.com +short | head -n 1)
echo "$CF_NS"You should see one of the Cloudflare nameserver hostnames assigned to your domain.
Next, this command asks that Cloudflare nameserver directly about the shadowed name, without recursion, so you see only what your zone says:
dig @"$CF_NS" www.sub.example.com A +norecurseExpected result: the ANSWER SECTION is missing or empty, and the AUTHORITY SECTION lists the NS records for sub.example.com. That is a referral. If the delegation uses in-zone nameservers, the glue appears in the ADDITIONAL SECTION.
Now this command follows the full path from the root servers down, the way a resolver would. The BIND manual says +trace "toggles tracing of the delegation path from the root name servers" and turns recursion off:
dig +trace www.sub.example.com ARead it from the bottom. The second-to-last block should come from a Cloudflare nameserver and hand you the sub.example.com NS records. The last block shows the answer from the delegated nameserver.
Finally, this command asks one delegated nameserver directly. Replace ns1.example.org with a nameserver from the NS records you found:
dig @ns1.example.org www.sub.example.com A +shortIf it prints an IP address, the delegated zone already has a record for this name. If it prints nothing, the delegated zone has no such record, and the copy in Cloudflare was never doing anything.
Decide what to do with each record
Made-up example: Sara runs example.com on Cloudflare. Two years ago her team delegated docs.example.com to a documentation host with three NS records. Last month someone added status.docs.example.com as an A record pointing to 203.0.113.25 in Cloudflare, and it never resolved. The shadowed record warning in the dashboard explains why: the record is under the docs delegation, so only the documentation host's nameservers can answer for it.
Option A: The record belongs in the delegated zone
This is Sara's case: the delegation is correct, the record was added in the wrong place.
- Log in to whoever runs the delegated nameservers and create the record there with the same name, type and value.
- Wait for it to show up with
dig @ns1.example.org status.docs.example.com A +short. - Once that returns the right IP, delete the shadowed copy in Cloudflare.
To delete in the dashboard, go to the DNS Records page, select Edit on the record, select Delete, then select Delete again to confirm. Nothing changes for visitors, because the copy you deleted was never being served.
Option B: The record is a leftover
The delegated zone already has the right answer and the Cloudflare copy is old, often left behind after a subdomain moved to an outside provider.
Check with dig @ns1.example.org that the delegated nameserver returns the value you expect. Then delete the shadowed copy using the same Edit > Delete > Delete path.
Quick tip: Cloudflare limits how many records a zone can hold. At the time of writing (26 October 2026), its docs list 200 records for Free zones created on or after 1 September 2024, 1,000 for Free zones created before that date, and 3,500 for Pro and Business. Since 6 October 2026, the DNS Records page shows a warning once you have used 85% of your quota. If you are close, clearing out records that do nothing is an easy first step.
Option C: The delegation itself is the mistake
Sometimes the NS record is the leftover, for example the subdomain moved back to Cloudflare. Removing the NS records makes Cloudflare authoritative again, and the shadowed records start being served.
Heads up: this is the risky one. The moment you delete the delegating NS records, resolvers stop asking the delegated nameservers. Any record that exists only over there disappears for your visitors, and the subdomain can go offline.
Do this in order:
- Make sure your zone export from Step 1 is saved.
- Get a full list of records from the delegated provider, not only the ones you know about.
- Compare that list with the shadowed records Cloudflare showed you for this delegation. Add anything missing in Cloudflare first. It will be shadowed until the delegation goes, which is fine.
- Delete every
NSrecord at that delegation name, using Edit > Delete > Delete on each one. - Delete any glue
AorAAAArecords that only existed for that delegation. - Run the checks in the next section.
Why this matters: TTL (time to live) controls how long a record stays valid in caches, so for a while some resolvers may still use the old NS answers and reach the old nameservers. Keep the old provider running until that passes. Our guide on lowering DNS TTL before a hosting move explains how to plan that window.
If the delegated nameservers used DNSSEC, Cloudflare's delegation guide says you add a DS record in Cloudflare for that delegation. Review it together with the NS records, and see how DNSSEC and DS records work on Cloudflare before you change it.
Option D: Glue, live or dead
Live glue, with is_glue: true and no dead_glue, is required. Deleting it can break the delegation, because resolvers lose the nameserver's address.
Dead glue, with dead_glue: true, is never served. Cloudflare's docs say it does not cause resolution failures, and that it is either a leftover you can safely remove or a sign that the shallower delegation was created in error.
Here is that dead glue case from Cloudflare's reference page:
sub.example.com NS ns1.sub.example.com.
a.sub.example.com NS ns1.a.sub.example.com.
ns1.a.sub.example.com A 192.0.2.1The sub.example.com delegation takes authority for everything under it, so the glue for a.sub.example.com is never served from your zone. Before you remove dead glue, Cloudflare says to verify that the external nameserver for the shallower delegation, here sub.example.com, already holds the correct records for the deeper subdomain.
How to check it worked
Run these after each change, and allow up to the record's TTL for cached answers to clear.
- API recount: run the
jqcommand from Step 3 again. Records you moved or deleted should be gone from the list. Live glue should still be there. - Delegation count: if you kept the delegation, the
NSrecord'sshadowed_records_countshould be lower. If it dropped to zero, the field disappears, because Cloudflare omits it when the count is zero. - Option A or B:
dig @ns1.example.org status.docs.example.com A +shortreturns the value you set at the delegated provider, anddig +traceends with the same answer. - Option C:
dig @"$CF_NS" www.sub.example.com A +norecursenow returns anANSWER SECTIONwith your record, and no longer a referral.dig +traceshould end at a Cloudflare nameserver. - Dashboard: the shadowed warnings for the records you handled are gone.
- Browser: open any site on the subdomain and confirm it loads.
Troubleshooting
"I edit the record in Cloudflare and nothing changes"
Symptom: you change an A record, save, wait, and dig still shows the old IP, or no IP. Cause: the record is shadowed, so Cloudflare does not answer with it. Fix: run the shadowing_name request from Step 5 to find the delegation, then change the record at the delegated nameservers instead (Option A).
The API returns an error when I filter by delegation
Symptom: a request with shadowed_by_name=sub.example.com fails. Cause: Cloudflare's docs say shadowed_by_name requires include_shadow_metadata=true, and supplying it without that flag returns an error. Passing the apex, example.com, also fails, because the value must be a subdomain. Fix: add include_shadow_metadata=true to the same URL and use a subdomain name.
The response has no shadowed_by fields at all
Symptom: you know a record is shadowed, but the JSON has no shadow fields. Cause: either you forgot include_shadow_metadata=true, or the page held more than 1,000 records, in which case Cloudflare returns records without shadow metadata. Fix: add the flag and set per_page=100, then walk through every page using total_pages from result_info.
The API says the token cannot read the zone
Symptom: an authentication or permission error on every request. Cause: the token was scoped to a different zone, or has no DNS permission. Cloudflare's token docs say a token with Zone DNS Read for one zone returns an error for DNS reads on any other zone. Fix: edit the token under My Profile > API Tokens and add Zone DNS Read for this zone, or create a new token.
A proxied record under the subdomain gets no Cloudflare protection
Symptom: a record under a delegated name is set to Proxied, but traffic does not go through Cloudflare. Cause: Cloudflare's docs say its "CDN and security services are not applied to delegated subdomains." The record is shadowed, so the proxy setting has no effect. Fix: if you need Cloudflare's proxy on that name, the subdomain has to be served by Cloudflare. That means Option C, carefully, or asking the delegated provider what protection they offer.
I deleted a glue record and the subdomain stopped resolving
Symptom: dig +trace fails after the Cloudflare step, because resolvers cannot find the delegated nameserver's address. Cause: the record was live glue, not dead glue, and the delegation's nameserver lives inside the delegated subdomain. Fix: open your Step 1 export, find the line for that A or AAAA record, and re-create it from the DNS Records page with Add record, using the same name and IP.
The one message worth forwarding
Copy this to whoever manages your DNS:
"Hi, Cloudflare is showing shadowed record warnings on our zone. A shadowed record sits under a subdomain we delegated with an NS record, so Cloudflare does not serve it. Could you export the zone first, then list the shadowed records with the API using include_shadow_metadata=true, and for each one tell me if it should move to the delegated nameservers or be deleted? Please do not delete any NS delegation until we have confirmed that every record on the other side also exists in Cloudflare."
Takeaway: a shadowed record is a note the front desk will never read, so find out who really answers for that name, put the record there, and only then tidy up.
Reader questions
Can a subdomain delegation point to Cloudflare's own nameservers?
Yes. Cloudflare's docs note that the delegated nameservers are not necessarily from a different provider, for example in a Cloudflare subdomain setup. Records under that delegation are still shadowed in the parent zone.
Which record types can be shadowed?
Any record type below a delegation can be shadowed, including A, AAAA, CNAME, MX, TXT, SRV, CAA, HTTPS, SVCB and NS records at deeper names.
Is shadow metadata saved in my zone?
No. Cloudflare computes shadow metadata on demand when you read records and never stores it, and it is only returned when you ask for it.
Do create and update API calls return shadow metadata too?
Yes. Cloudflare says shadow metadata is available on individual record reads, create and update responses, list requests and batch requests when you set include_shadow_metadata=true.
Does a CNAME record at a nameserver's name count as glue?
No. Cloudflare treats only A and AAAA records as glue, so a CNAME at the same name as an NS target is not glue.
How many NS records can one delegation have in Cloudflare?
Cloudflare supports up to 10 NS records per delegation name and recommends seven or fewer, in line with RFC 1912. Creating more than 10 is not supported.
Was this guide helpful?
Help us make the next update better.
Sources & further reading
- Cloudflare DNS changelog
- Cloudflare Docs: Shadowed records
- Cloudflare Docs: Delegate subdomains
- Cloudflare Docs: Manage DNS records
- Cloudflare Docs: Import and export records
- Cloudflare Docs: DNS records overview and quotas
- Cloudflare API: List DNS Records
- Cloudflare Docs: Create API token
- BIND 9 manual pages (dig)
- jq manual
What changed
Added an original wide cover and aligned the visible, social and structured-data image metadata after a primary-source fact check.
Originally published . About our editorial updates.


