This is a sample report. It comes from a real scan of Buggy Demo Shop — a small practice site we built and deliberately filled with defects, so that one report can show every kind of finding the bot produces. The addresses read localhost because that is where the practice site runs. Nothing here is a real shop, and no real site was scanned to make this page. Two things read oddly precisely because the target is a local practice site, and they are worth knowing before you run this on your own: Domain authority and Performance are empty because both rate a public domain — there is nothing for them to measure on localhost (authority also wants a free OpenPageRank key). And every page scores 100 on PageRank because this little site links every page to every other one, so the graph is perfectly symmetric; on a real site the scores spread out and the ranking becomes meaningful.

TesterBot — QA report

Target: http://localhost:8099/
Generated: 2026-08-27 20:43 UTCDuration: 48.8sPages tested: 10Links checked: 10Controls clicked: 3Forms tested: 4Logged in: noDanger mode: off

Site intelligence

Authority · performance · technology · hosting for the home page
Domain authority
No OpenPageRank key set (free at openpagerank.com).
Get a free key →
Performance · mobile
PageSpeed Insights did not respond (adding a key raises the limit: Google Cloud → PageSpeed API).
Technology stack · 2
Programming languages
Python
JavaScript libraries
core-js
Server: BaseHTTP/0.6 Python/3.11.15IP: 127.0.0.1

Link graph

data we crawled ourselves — the same core as Ahrefs
Every link was recorded while the site was crawled. The PageRank below is the same calculation Google and Ahrefs use — it ranks the site's own "strongest" pages by its internal link structure. Raw data: linkgraph.json and linkgraph-edges.csv.
9
Pages
82
Links (edges)
81
Internal
1
External
1
External domains
0
nofollow
Strongest pages · internal PageRank
/100.0
/login100.0
/team100.0
/slow100.0
/contact100.0
/does-not-exist100.0
/pricing100.0
/about100.0
Domains linked out to
example.com1 link · 1 pages
5
Critical
8
High
8
Medium
14
Low
6
Info
Click a tile to filter by severity, or a category chip below. Every finding expands to show the evidence, the URL and a suggested fix.
Accessibility · 7SEO · 5Security Headers · 5Network · 3Security · 3Forms · 3HTTP Status · 2Broken Link · 2Content · 2Responsive · 2Dead Control · 2Exposed File · 1JavaScript Error · 1Broken Media · 1Performance · 1Skipped · 1
Critical
Environment file with secrets is publicly reachable: /.env
Exposed Filehttp://localhost:8099/.env

What this means

This file should not be served to the internet. It usually gets exposed by deploying the whole working directory.

Where

http://localhost:8099/.env

Evidence

{
  "status": 200,
  "excerpt": "DB_PASSWORD=hunter2\nAPI_KEY=sk-test-123\n"
}

Suggested fix

Block the path at the web server, or stop deploying the file.
Critical
Page returns HTTP 500
HTTP Statushttp://localhost:8099/broken

What this means

This page is linked from the site but does not load successfully.

Where

http://localhost:8099/broken

Evidence

{
  "status": 500
}

Suggested fix

Restore the page or remove/redirect the links pointing at it.
Critical
Clicking 'Show offers' throws: window.missingFunction is not a function
JavaScript Errorhttp://localhost:8099/

What this means

A JavaScript exception was raised as a direct result of clicking this control, so the feature behind it is broken.

Where

http://localhost:8099/

Element

#boom

Evidence

{
  "message": "window.missingFunction is not a function",
  "stack": "TypeError: window.missingFunction is not a function\n    at HTMLButtonElement.<anonymous> (http://localhost:8099/:24:10)",
  "control_html": "<button id=\"boom\">Show offers</button>"
}

Screenshot

screenshot

Suggested fix

Reproduce by clicking this control with DevTools open.
Critical
HTTP 500 on fetch: http://localhost:8099/api/offers
Networkhttp://localhost:8099/

What this means

A sub-request returned HTTP 500 while loading this page. A 5xx means the server itself errored.

Where

http://localhost:8099/

Evidence

{
  "request_url": "http://localhost:8099/api/offers",
  "status": 500,
  "method": "GET",
  "resource_type": "fetch"
}

Suggested fix

Fix the endpoint or stop the page from requesting it.
Critical
Site is served over plain HTTP
Securityhttp://localhost:8099/

What this means

All traffic, including anything typed into a form, is unencrypted and browsers will label the site 'Not secure'.

Where

http://localhost:8099/

Suggested fix

Install a TLS certificate and redirect http:// to https://.
High
HTTP 500 link: http://localhost:8099/broken
Broken Link9× across the sitehttp://localhost:8099/

What this means

A link on the site points to a URL that answers 500.

Where

http://localhost:8099/

Also on

  • http://localhost:8099/about
  • http://localhost:8099/contact
  • http://localhost:8099/does-not-exist
  • http://localhost:8099/hidden-offer
  • http://localhost:8099/login
  • http://localhost:8099/pricing
  • http://localhost:8099/slow

Evidence

{
  "target": "http://localhost:8099/broken",
  "status": 500,
  "link_text": "Broken",
  "found_on": [
    "http://localhost:8099/",
    "http://localhost:8099/about",
    "http://localhost:8099/contact",
    "http://localhost:8099/does-not-exist",
    "http://localhost:8099/hidden-offer",
    "http://localhost:8099/login",
    "http://localhost:8099/pricing",
    "http://localhost:8099/slow"
  ]
}

Suggested fix

Update the href or remove the link.
High
Images that fail to load
Broken Media2× across the sitehttp://localhost:8099/

What this means

The <img> resolved to a URL the browser could not render.

Where

http://localhost:8099/

Also on

  • http://localhost:8099/team

Element

html > body > img:nth-of-type(1)

Evidence

{
  "images": [
    {
      "src": "http://localhost:8099/img/missing-photo.png",
      "selector": "html > body > img:nth-of-type(1)"
    }
  ]
}

Suggested fix

Fix the image path or upload the missing file.
High
Server accepts an empty submission (validation is browser-side only)
Forms2× across the sitehttp://localhost:8099/pricing

What this means

The browser's own required-field check was removed and the same empty submission was then accepted by the server. Anyone using a script, a modified page or an old browser can post empty/garbage records.

Where

http://localhost:8099/pricing

Also on

  • http://localhost:8099/contact

Element

#nl

Evidence

{
  "required_fields": [
    "email"
  ],
  "final_url": "http://localhost:8099/subscribe-newsletter"
}

Screenshot

screenshot

Suggested fix

Validate every required field on the server, not only in HTML.
High
Placeholder / debug text visible to users: undefined
Contenthttp://localhost:8099/

What this means

Text that should never reach production is rendered on the page.

Where

http://localhost:8099/

Evidence

{
  "excerpt": "k This block is 1500px wide and overflows on mobile. Status: undefined"
}

Suggested fix

Replace the placeholder or fix the value that renders as junk.
High
Form does nothing when submitted with valid data
Formshttp://localhost:8099/pricing

What this means

No navigation, no network request and no message appeared. The form looks non-functional.

Where

http://localhost:8099/pricing

Element

#noop

Evidence

{
  "fields": [
    "promo"
  ]
}

Screenshot

screenshot

Suggested fix

Wire the form up to its handler / endpoint.
High
HTTP 404 on image: http://localhost:8099/img/missing-photo.png
Networkhttp://localhost:8099/

What this means

A sub-request returned HTTP 404 while loading this page. The resource is missing or forbidden.

Where

http://localhost:8099/

Evidence

{
  "request_url": "http://localhost:8099/img/missing-photo.png",
  "status": 404,
  "method": "GET",
  "resource_type": "image"
}

Suggested fix

Fix the endpoint or stop the page from requesting it.
High
HTTP 404 on image: http://localhost:8099/img/team.png
Networkhttp://localhost:8099/team

What this means

A sub-request returned HTTP 404 while loading this page. The resource is missing or forbidden.

Where

http://localhost:8099/team

Evidence

{
  "request_url": "http://localhost:8099/img/team.png",
  "status": 404,
  "method": "GET",
  "resource_type": "image"
}

Suggested fix

Fix the endpoint or stop the page from requesting it.
High
User input is rendered as raw HTML (output not escaped)
Securityhttp://localhost:8099/contact

What this means

TesterBot submitted the literal text '<b>TBQA7</b>' and the page rendered it as a real bold element instead of showing it as text. Anything a user types can therefore inject markup into the page.

Where

http://localhost:8099/contact

Element

html > body > form

Evidence

{
  "submitted": "<b>TBQA7</b>",
  "rendered_back_as": "<b>TBQA7</b>"
}

Suggested fix

HTML-escape user input before rendering it, or bind it as text content rather than innerHTML.
Medium
Images without an alt attribute
Accessibility2× across the sitehttp://localhost:8099/

What this means

Screen-reader users get no description; broken images show nothing.

Where

http://localhost:8099/

Also on

  • http://localhost:8099/team

Element

html > body > img:nth-of-type(1)

Evidence

{
  "images": [
    {
      "src": "http://localhost:8099/img/missing-photo.png",
      "selector": "html > body > img:nth-of-type(1)"
    }
  ]
}

Suggested fix

Add alt="…" (or alt="" for purely decorative images).
Medium
Links with no readable text
Accessibilityhttp://localhost:8099/

What this means

Icon-only or empty links are announced as 'link' with no context.

Where

http://localhost:8099/

Element

html > body > a:nth-of-type(2)

Evidence

{
  "links": [
    {
      "href": "http://localhost:8099/team",
      "selector": "html > body > a:nth-of-type(2)"
    }
  ]
}

Suggested fix

Add visible text, aria-label, or alt text on the inner icon.
Medium
Placeholder / debug text visible to users: lorem ipsum
Contenthttp://localhost:8099/team

What this means

Text that should never reach production is rendered on the page.

Where

http://localhost:8099/team

Evidence

{
  "excerpt": "m ContactPricingBroken SlowLogin Dead link Team Engineering Lorem ipsum dolor sit amet, consectetur adipiscing elit."
}

Suggested fix

Replace the placeholder or fix the value that renders as junk.
Medium
Form has no required fields at all
Formshttp://localhost:8099/login

What this means

None of the inputs are marked required, so a completely empty submission is accepted by the browser.

Where

http://localhost:8099/login

Element

html > body > form

Evidence

{
  "fields": [
    "user",
    "pass"
  ]
}

Suggested fix

Mark the mandatory inputs with the required attribute.
Medium
Unknown URLs return HTTP 200 instead of 404
HTTP Statushttp://localhost:8099/testerbot-does-not-exist-9f2c1a

What this means

A deliberately invalid path returned a normal 200 response. Search engines index junk pages and monitoring cannot tell real pages from typos.

Where

http://localhost:8099/testerbot-does-not-exist-9f2c1a

Evidence

{
  "status": 200
}

Suggested fix

Return status 404 for unknown routes (a styled 404 page is still 404).
Medium
Slow server response (TTFB 2003 ms)
Performancehttp://localhost:8099/slow

What this means

Time to first byte is dominated by server work, not the browser.

Where

http://localhost:8099/slow

Evidence

{
  "load_ms": 2011,
  "dom_ready_ms": 2011,
  "ttfb_ms": 2003,
  "transfer_kb": 1
}

Suggested fix

Cache the response, add an index, or move work off the request path.
Medium
Horizontal scrolling on mobile (390px)
Responsivehttp://localhost:8099/

What this means

Content is 1524px wide in a 390px viewport, so the user has to scroll sideways. Usually one element with a fixed width or an unwrapped table.

Where

http://localhost:8099/

Evidence

{
  "viewport_width": 390,
  "content_width": 1524,
  "overflow_px": 1134,
  "widest_elements": [
    {
      "selector": "div.wide",
      "width": 1500,
      "right": 1524,
      "text": "This block is 1500px wide and overflows on mobile."
    }
  ]
}

Screenshot

screenshot

Suggested fix

Find the overflowing element and give it max-width:100% / overflow-x:auto.
Medium
Horizontal scrolling on tablet (820px)
Responsivehttp://localhost:8099/

What this means

Content is 1524px wide in a 820px viewport, so the user has to scroll sideways. Usually one element with a fixed width or an unwrapped table.

Where

http://localhost:8099/

Evidence

{
  "viewport_width": 820,
  "content_width": 1524,
  "overflow_px": 704,
  "widest_elements": [
    {
      "selector": "div.wide",
      "width": 1500,
      "right": 1524,
      "text": "This block is 1500px wide and overflows on mobile."
    }
  ]
}

Screenshot

screenshot

Suggested fix

Find the overflowing element and give it max-width:100% / overflow-x:auto.
Low
All page content should be contained by landmarks
Accessibility31× across the sitehttp://localhost:8099/

What this means

Ensure all page content is contained by landmarks

Where

http://localhost:8099/

Also on

  • http://localhost:8099/about
  • http://localhost:8099/hidden-offer
  • http://localhost:8099/pricing
  • http://localhost:8099/team
  • http://localhost:8099/contact
  • http://localhost:8099/slow
  • http://localhost:8099/login
  • http://localhost:8099/does-not-exist

Evidence

{
  "rule": "region",
  "impact": "moderate",
  "elements_affected": 7,
  "examples": [
    {
      "target": "h1",
      "html": "<h1>Buggy Demo Shop</h1>",
      "summary": "Fix any of the following:\n  Some page content is not contained by landmarks"
    },
    {
      "target": "p:nth-child(4)",
      "html": "<p>Everything on this page is broken on purpose.</p>",
      "summary": "Fix any of the following:\n  Some page content is not contained by landmarks"
    },
    {
      "target": "img[src$=\"missing-photo.png\"]",
      "html": "<img src=\"/img/missing-photo.png\" width=\"120\" height=\"80\">",
      "summary": "Fix any of the following:\n  Some page content is not contained by landmarks"
    },
    {
      "target": "img[src$=\"logo.png\"]",
      "html": "<img src=\"/img/logo.png\" alt=\"Logo\" width=\"60\" height=\"60\">",
      "summary": "Fix any of the following:\n  Some page content is not contained by landmarks"
    },
    {
      "target": "a[target=\"_blank\"]",
      "html": "<a href=\"https://example.com/definitely-missing-page-xyz\" target=\"_blank\">External broken link</a>",
      "summary": "Fix any of the following:\n  Some page content is not contained by landmarks"
    },
    {
      "target": "div",
      "html": "<div class=\"wide\">This block is 1500px wide and overflows on mobile.</div>",
      "summary": "Fix any of the following:\n  Some page content is not contained by landmarks"
    }
  ],
  "reference": "https://dequeuniversity.com/rules/axe/4.10/region?application=axeAPI"
}

Suggested fix

See the axe-core rule 'region': https://dequeuniversity.com/rules/axe/4.10/region?application=axeAPI
Low
Document should have one main landmark
Accessibility9× across the sitehttp://localhost:8099/

What this means

Ensure the document has a main landmark

Where

http://localhost:8099/

Also on

  • http://localhost:8099/about
  • http://localhost:8099/hidden-offer
  • http://localhost:8099/pricing
  • http://localhost:8099/team
  • http://localhost:8099/contact
  • http://localhost:8099/slow
  • http://localhost:8099/login
  • http://localhost:8099/does-not-exist

Evidence

{
  "rule": "landmark-one-main",
  "impact": "moderate",
  "elements_affected": 1,
  "examples": [
    {
      "target": "html",
      "html": "<html lang=\"en\">",
      "summary": "Fix all of the following:\n  Document does not have a main landmark"
    }
  ],
  "reference": "https://dequeuniversity.com/rules/axe/4.10/landmark-one-main?application=axeAPI"
}

Suggested fix

See the axe-core rule 'landmark-one-main': https://dequeuniversity.com/rules/axe/4.10/landmark-one-main?application=axeAPI
Low
No meta description
SEO8× across the sitehttp://localhost:8099/about

What this means

Search engines will invent a snippet for this page.

Where

http://localhost:8099/about

Also on

  • http://localhost:8099/hidden-offer
  • http://localhost:8099/pricing
  • http://localhost:8099/team
  • http://localhost:8099/contact
  • http://localhost:8099/slow
  • http://localhost:8099/login
  • http://localhost:8099/does-not-exist

Suggested fix

Add <meta name="description" content="…">.
Low
Fields rely on placeholder text instead of a label
Accessibility4× across the sitehttp://localhost:8099/pricing

What this means

The placeholder disappears as soon as the user types, so the field loses its description.

Where

http://localhost:8099/pricing

Also on

  • http://localhost:8099/contact

Element

#noop > input

Evidence

{
  "fields": [
    {
      "selector": "#noop > input",
      "type": "text",
      "name": "promo",
      "placeholderOnly": true
    }
  ]
}

Suggested fix

Add a real <label> in addition to the placeholder.
Low
2 pages share the same <title>: "Company"
SEO2× across the sitehttp://localhost:8099/about

What this means

Duplicate titles hurt search results and make browser tabs ambiguous.

Where

http://localhost:8099/about

Also on

  • http://localhost:8099/team

Evidence

{
  "pages": [
    "http://localhost:8099/about",
    "http://localhost:8099/team"
  ]
}

Suggested fix

Give every page a distinct title.
Low
Heading levels should only increase by one
Accessibilityhttp://localhost:8099/team

What this means

Ensure the order of headings is semantically correct

Where

http://localhost:8099/team

Evidence

{
  "rule": "heading-order",
  "impact": "moderate",
  "elements_affected": 1,
  "examples": [
    {
      "target": "h4",
      "html": "<h4>Engineering</h4>",
      "summary": "Fix any of the following:\n  Heading order invalid"
    }
  ],
  "reference": "https://dequeuniversity.com/rules/axe/4.10/heading-order?application=axeAPI"
}

Suggested fix

See the axe-core rule 'heading-order': https://dequeuniversity.com/rules/axe/4.10/heading-order?application=axeAPI
Low
HTTP 403 link: https://example.com/definitely-missing-page-xyz
Broken Linkhttp://localhost:8099/

What this means

A link on the site points to a URL that answers 403. (external site)

Where

http://localhost:8099/

Evidence

{
  "target": "https://example.com/definitely-missing-page-xyz",
  "status": 403,
  "link_text": "External broken link",
  "found_on": [
    "http://localhost:8099/"
  ]
}

Suggested fix

Update the href or remove the link.
Low
Control appears to do nothing: 'Click me'
Dead Controlhttp://localhost:8099/

What this means

After clicking, the URL, the DOM, the network and the console were all unchanged. Either the handler is missing or the effect is invisible (e.g. copy-to-clipboard). Worth a manual look.

Where

http://localhost:8099/

Element

#dead

Evidence

{
  "html": "<button id=\"dead\">Click me</button>"
}

Screenshot

screenshot

Suggested fix

Confirm the control has a working handler.
Low
Control appears to do nothing: '☰'
Dead Controlhttp://localhost:8099/

What this means

After clicking, the URL, the DOM, the network and the console were all unchanged. Either the handler is missing or the effect is invisible (e.g. copy-to-clipboard). Worth a manual look.

Where

http://localhost:8099/

Element

html > body > button:nth-of-type(3)

Evidence

{
  "html": "<button aria-hidden=\"false\"><span class=\"icon\">☰</span></button>"
}

Screenshot

screenshot

Suggested fix

Confirm the control has a working handler.
Low
Page has no <h1>
SEOhttp://localhost:8099/team

What this means

No top-level heading was found in the rendered page.

Where

http://localhost:8099/team

Suggested fix

Give the page exactly one <h1> describing its content.
Low
Links open a new tab without rel=noopener
Securityhttp://localhost:8099/

What this means

target="_blank" without rel="noopener" lets the opened page reach back through window.opener in older browsers.

Where

http://localhost:8099/

Element

html > body > a:nth-of-type(1)

Evidence

{
  "links": [
    {
      "href": "https://example.com/definitely-missing-page-xyz",
      "selector": "html > body > a:nth-of-type(1)"
    }
  ]
}

Suggested fix

Add rel="noopener noreferrer" to those links.
Low
Missing security header: Content-Security-Policy
Security Headershttp://localhost:8099/

What this means

The site does not send the Content-Security-Policy response header.

Where

http://localhost:8099/

Evidence

{
  "present_headers": [
    "content-length",
    "content-type",
    "date",
    "server"
  ]
}

Suggested fix

Add the Content-Security-Policy header at the web server or CDN level.
Low
Missing security header: X-Content-Type-Options
Security Headershttp://localhost:8099/

What this means

The site does not send the X-Content-Type-Options response header.

Where

http://localhost:8099/

Evidence

{
  "present_headers": [
    "content-length",
    "content-type",
    "date",
    "server"
  ]
}

Suggested fix

Add the X-Content-Type-Options header at the web server or CDN level.
Low
Missing security header: X-Frame-Options
Security Headershttp://localhost:8099/

What this means

The site does not send the X-Frame-Options response header.

Where

http://localhost:8099/

Evidence

{
  "present_headers": [
    "content-length",
    "content-type",
    "date",
    "server"
  ]
}

Suggested fix

Add the X-Frame-Options header at the web server or CDN level.
Info
Heading levels are skipped
Accessibilityhttp://localhost:8099/team

What this means

e.g. an H2 is followed directly by an H4, which confuses screen-reader navigation.

Where

http://localhost:8099/team

Evidence

{
  "skips": [
    {
      "from": 2,
      "to": 4,
      "text": "Engineering"
    }
  ]
}

Suggested fix

Use heading levels in order without gaps.
Info
No favicon declared
SEOhttp://localhost:8099/

Where

http://localhost:8099/

Suggested fix

Add <link rel="icon" …> so tabs and bookmarks look right.
Info
No Open Graph tags
SEOhttp://localhost:8099/

What this means

Links shared on social media / chat apps will have no preview.

Where

http://localhost:8099/

Suggested fix

Add og:title, og:description and og:image.
Info
Missing security header: Referrer-Policy
Security Headershttp://localhost:8099/

What this means

The site does not send the Referrer-Policy response header.

Where

http://localhost:8099/

Evidence

{
  "present_headers": [
    "content-length",
    "content-type",
    "date",
    "server"
  ]
}

Suggested fix

Add the Referrer-Policy header at the web server or CDN level.
Info
Server software and version are advertised in response headers
Security Headershttp://localhost:8099/

What this means

Server/X-Powered-By reveals: BaseHTTP/0.6 Python/3.11.15

Where

http://localhost:8099/

Evidence

{
  "server": "BaseHTTP/0.6 Python/3.11.15",
  "x_powered_by": ""
}

Suggested fix

Suppress the version banner in the web server configuration.
Info
Destructive-looking control not clicked: 'Delete my account'
Skippedhttp://localhost:8099/pricing

What this means

TesterBot avoids controls that look like delete / pay / logout so it cannot damage real data. Re-run with --danger-mode on a staging copy to include them.

Where

http://localhost:8099/pricing

Element

html > body > button

Evidence

{
  "html": "<button>Delete my account</button>"
}
No findings match the current filter.

Pages tested

URLTitleStatusLoadLinksClicksFormsFindings
http://localhost:8099/Buggy Demo Shop20060 ms113021
http://localhost:8099/aboutCompany20011 ms9003
http://localhost:8099/hidden-offerSecret Offer20013 ms9003
http://localhost:8099/pricingPricing20013 ms9027
http://localhost:8099/teamCompany20056 ms90010
http://localhost:8099/contactContact us20010 ms9016
http://localhost:8099/broken5000001
http://localhost:8099/slowSlow page2002011 ms9004
http://localhost:8099/loginLogin20013 ms9014
http://localhost:8099/does-not-existNot found20012 ms9003