An ADA website demand letter starts two clocks. Your attorney runs the legal one; this article is about the technical one, which decides whether your attorney negotiates from facts or from guesses.

First, plainly: this is not legal advice, and Baclion is not a law firm. Everything below happens alongside counsel, never instead of it. If the letter hasn't reached an attorney yet, send it now and read the rest while you wait for a call back. Letters are not rare, and they are not always one-time events. UsableNet's 2025 year-end report counted more than 5,000 digital accessibility lawsuits in federal and state courts. The same report found that 1,427 of them targeted companies that had already been sued. Resolving a letter without fixing the site leaves the same barriers waiting for the next one.

The 72-hour timeline at a glance

WindowTechnical workWhat goes to your attorney
Hours 0 to 2Send the letter to counsel, name one technical lead, and pause nonessential releases to the cited pagesThe letter, the technical lead's contact details, and a list of who has seen it
Hours 2 to 8Capture screenshots, rendered HTML, network logs, accessibility snapshots, and platform versions for every cited URLA dated, hashed evidence archive
Hours 4 to 24Reproduce each cited barrier with the named screen reader and browserA claim-by-claim reproduction log
Hours 12 to 36Sort any attached scan output into real barriers, low-impact failures, and noiseA short triage summary
Hours 24 to 48Fix obvious blockers in source code, with before-and-after evidenceA change log with commit references and deploy times
Hours 48 to 72Assemble the evidence pack and a dated remediation plan, and start monitoringThe evidence pack and timeline

Ask your attorney early whether the technical work should be commissioned through their office. That choice can affect how the findings are treated later, and it's theirs to make.

Preserve the site before you touch it

You are about to change things, so capture the state the letter describes before any fix ships. Once a deploy goes out, you can't reconstruct what a page looked like last Tuesday.

For every URL the letter names, plus the home page and any journey it describes, collect:

  • A full-page screenshot and the rendered HTML, meaning the DOM after scripts run, not just the source file
  • An accessibility snapshot, which records the roles and names a screen reader would get
  • A HAR file of the page load, which lists every request, including third-party scripts
  • The capture time in UTC, plus the browser and its version
  • Platform versions: CMS, theme, plugins or apps, and the git commit or build ID that is live
  • The tag manager container version, since third-party scripts change pages too

A short Playwright script does most of this in one pass and hashes the files so nobody can later question whether they changed:

// preserve.mjs: node preserve.mjs urls.txt
import { chromium } from "playwright";
import fs from "node:fs";
import crypto from "node:crypto";

const urls = fs.readFileSync(process.argv[2], "utf8").split("\n").filter(Boolean);
const dir = `evidence-${new Date().toISOString().replace(/[:.]/g, "-")}`;
fs.mkdirSync(dir);

const browser = await chromium.launch();
const context = await browser.newContext({ recordHar: { path: `${dir}/session.har` } });
const page = await context.newPage();
const log = [];

for (const [i, url] of urls.entries()) {
  const base = `${dir}/page-${i}`;
  await page.goto(url, { waitUntil: "load" });
  await page.screenshot({ path: `${base}.png`, fullPage: true });
  fs.writeFileSync(`${base}.html`, await page.content());
  fs.writeFileSync(`${base}.aria.yml`, await page.locator("body").ariaSnapshot());
  log.push({ url, capturedAt: new Date().toISOString(), browser: browser.version() });
}
await context.close(); // writes the HAR file
await browser.close();

for (const file of fs.readdirSync(dir)) {
  const sha256 = crypto.createHash("sha256").update(fs.readFileSync(`${dir}/${file}`)).digest("hex");
  log.push({ file, sha256 });
}
fs.writeFileSync(`${dir}/manifest.json`, JSON.stringify(log, null, 2));

Store the folder somewhere read-only and tell your attorney where it is.

Reproduce each barrier with the technology the letter names

Letters often name the assistive technology the plaintiff used: "JAWS with Chrome," "NVDA," "VoiceOver on iPhone." Test each claim with that same pairing, and write down both versions. A barrier that appears in JAWS with Chrome and not in VoiceOver with Safari is still a barrier; it's also useful detail for your attorney.

For each claim, record:

  1. The URL and the steps you took, written so someone else could repeat them
  2. What you expected and what actually happened
  3. What the screen reader said. NVDA's Speech Viewer and JAWS's speech history give you text you can paste, and a screen recording with audio is better still.
  4. A result: reproduced, partially reproduced, not reproduced, or can't determine (for example, because the page no longer exists)

"Not reproduced" doesn't mean "false." The plaintiff may have used a different device, a different date, or a path through the site you didn't try. Record what you tested and stop there. Keep the notes factual and leave the arguing to counsel.

Separate scanner noise from real barriers

Many letters attach automated scan output with hundreds of "errors." Some are real. Some are the same error counted many times. Some aren't failures at all. Sorting them takes an experienced tester a few hours and saves everyone days.

  • Real barriers that block a task. An unlabeled email field in checkout, a modal that traps keyboard focus, a navigation link that's an image with no text alternative. These go to the top of the fix list.
  • Real failures with lower impact. A decorative image announced by its file name, or a low-contrast footer link. Fix them, but not before the blockers.
  • Duplicates. A missing label in the site header appears on every page, so a 300-page crawl reports it 300 times. It is one bug in one component, and one fix.
  • Noise. Best-practice warnings reported as violations (a skipped heading level isn't a WCAG failure on its own), contrast "failures" on disabled controls or logos (which SC 1.4.3 exempts), and items that need human judgment flagged as definite errors.

The output of this step is a short list your attorney can read in five minutes: what's real, what's fixed, and what's next.

Fix the obvious blockers, and write everything down

Some barriers take an afternoon to fix. An icon-only button with no name is a one-line change:

<!-- Before: announced as "button" -->
<button class="search-toggle"><svg>…</svg></button>

<!-- After: announced as "Search, button" -->
<button class="search-toggle" aria-label="Search">
  <svg aria-hidden="true" focusable="false">…</svg>
</button>

Before you deploy anything to the cited pages, tell your attorney, since the timing of fixes can matter to their strategy. Then document every change the same way: the finding it addresses, the before evidence from your archive, the pull request or commit, the deploy time in UTC, and an after retest with the same screen reader and browser.

Fix in source code. Don't ship a script that patches the DOM after the page loads, and don't install an overlay as a panic response. An overlay injects JavaScript that tries to repair the page in the browser; the source code the letter describes is unchanged, and anyone testing without the widget still meets the original barriers. In its 2025 order against overlay vendor accessiBe, the FTC required a $1 million payment and barred the company from claiming, without evidence, that its automated product can make any website conform to WCAG. A widget installed the night a letter arrives looks like action. It isn't evidence of anything.

A few other panic moves to avoid: replying to the plaintiff's firm yourself, deleting cited pages before they're preserved, rewriting your accessibility statement to claim conformance you haven't tested, and posting about the letter in public.

Build the evidence pack your attorney needs

By hour 72, hand your attorney one folder with a one-page index. Inside:

  • Scope and method. What was tested, when, by which role on your team, with which browsers and assistive technology.
  • The preservation archive. Screenshots, HTML, HAR files, accessibility snapshots, platform versions, and the hash manifest.
  • The claim matrix. One row per barrier in the letter: URL, WCAG 2.2 success criterion, reproduction result, severity, and status.
  • The change log. Every fix shipped so far, with commit references, deploy times, and retest results.
  • A dated remediation plan. Remaining issues, owners, and realistic target dates. Your attorney will use these dates in conversations with the other side, so don't promise what your team can't ship.
  • A plan beyond the letter. The cited pages are a sample, not the boundary. Include a full audit of key templates and journeys on the timeline.

After the third day

The letter was about specific pages on specific dates. What protects you next is knowing when anything changes. Set up scheduled scans of the cited pages and your key journeys, alerts when a fixed issue comes back, and manual screen reader checks on a regular cadence, and keep the results in the same evidence folder.

If you'd rather not run the first 72 hours alone, our demand-letter technical support works through your attorney and starts at $2,400. For what comes after, Baclion Watch monitoring keeps the fixes fixed and the record current.

Sources

  1. UsableNet, 2025 Year-End Digital Accessibility Lawsuit Report
  2. Federal Trade Commission, press release: FTC Approves Final Order Requiring accessiBe to Pay $1 Million
  3. ADA.gov: Guidance on Web Accessibility and the ADA
  4. W3C: Web Content Accessibility Guidelines (WCAG) 2.2
  5. W3C WAI: Evaluating Web Accessibility Overview