Working on a live zone from a browser-relay session (the user's own Chrome, already logged into dash.cloudflare.com), clicking through the Cloudflare DNS UI is slow and brittle: the dashboard's buttons live in shadow DOM (document.querySelectorAll('button') from page context returns nothing useful, and a puppeteer text/Add selector hit a sidebar overlay instead of the dialog's Add button, silently doing nothing).
The reliable path: from a page context already on dash.cloudflare.com, fetch('/api/v4/...', {credentials:'include'}) is authenticated by the dashboard session cookie. No API token, no CSRF header needed. Verified working for:
GET /api/v4/zones?name=<domain>-> zone idGET|POST /api/v4/zones/<zone>/dns_records(POST body{type,name,content,ttl:1,proxied,comment};ttl:1= Auto)PUT /api/v4/accounts/<acct>/workers/scripts/<name>with a multipart FormData body (metadataBlob ={main_module:'worker.js',compatibility_date:'...'}, plus the module file) -> deploys a module WorkerPOST /api/v4/zones/<zone>/workers/routes{pattern:'host/*', script:'<name>'}
When the UI genuinely must be used (features that provision server-side state, e.g. enabling DMARC Management to mint a rua= report address), two things that worked where selectors failed: (1) screenshot first to see the real button, but note that with a relay browser tab.screenshot fails with "tab is not visible" until page.bringToFront() (tab.bringToFront does not exist); (2) click by walking shadow roots and calling .click() on the element whose innerText exactly matches, rather than using a text selector that can match an overlay.
Also: relay tab handles die when another tab is opened/navigated in the same browser ("Attempted to use detached Frame", "Execution context is not available in detached frame"). Recover by closing that tool session and re-opening with app.target set to a URL substring of the tab you want, rather than assuming the handle survives.
After any write, verify out-of-band rather than trusting the UI: dig +short TXT <name> @1.1.1.1 and a re-GET of the API endpoint. The Add-button no-op above was only caught because the follow-up GET dns_records?name=_dmarc... came back empty.