The Scan API (running on port 3002 by default) is responsible for analyzing provided HTML content to identify common accessibility issues. Currently, it focuses on:
aria-label attributes (presence, emptiness).
<img> tag alt text (presence, emptiness, content).
<html> tag for the presence of a lang attribute.
Elements with positive tabindex values.
Links (<a> tags) with generic text like "click here".
Empty <button> elements that lack an aria-label.
The API processes the HTML line by line and generates a report detailing its findings.
Main Endpoint: POST /
This endpoint accepts HTML content and returns an accessibility scan report.
Request
Method:POST
Content-Type:application/json
Request Body Limit:15mb
Body:
{
"htmlContent": "string (The raw HTML content to be scanned)"
}
Validation: The htmlContent field (as a string) is required in the request body.
Responses
Success (200 OK)
A successful scan returns a JSON object containing the analysis report.
{
"success": true,
"message": "Scan of the provided htmlContent completed successfully.",
"report": {
"summary": "string (An overall summary of the findings. The exact message varies based on issues found, informational details, or if no relevant elements were detected. E.g., 'Scan complete. Found: 2 empty 'aria-label' instance(s), 1 image(s) missing alt. (1 'aria-label' instance(s) with content; Processed 3 total image(s); 1 of which had non-empty alt text).')",
"issuesFound": "number (Total count of critical issues like empty aria-labels or missing/empty alt text)",
"categories": {
"documentStructure": {
"htmlLang": {
"missing": "boolean (True if the lang attribute is missing on the tag)",
"wcagLink": "string (URL to WCAG guidance, e.g., https://www.w3.org/WAI/WCAG21/Understanding/language-of-page.html)",
"suggestion": "string (Suggestion for fixing the issue, e.g., Ensure the `` tag has a `lang` attribute...)",
"details": [ // Array with one item if missing
{
"lineNumber": "number",
"fullLineContent": "string (The full tag line)",
"matchedString": "string (The tag itself)",
"matchStartIndexInLine": "number"
}
]
}
},
"interactiveElements": {
"totalIssues": "number (Total issues found within interactive elements: positive tabindex + generic links + empty buttons)",
"positiveTabindex": {
"wcagLink": "string (URL to WCAG guidance)",
"suggestion": "string (Suggestion for fixing the issue)",
"count": "number (Count of elements with tabindex > 0)",
"details": [
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (e.g., tabindex=\"1\")",
"attributeValue": "string (e.g., \"1\")",
"matchStartIndexInLine": "number"
}
]
},
"genericLinkText": {
"wcagLink": "string (URL to WCAG guidance)",
"suggestion": "string (Suggestion for fixing the issue)",
"count": "number (Count of links with generic text)",
"details": [
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (The full ... tag)",
"linkText": "string (The text content of the link)",
"matchStartIndexInLine": "number"
}
]
},
"emptyButtons": {
"wcagLink": "string (URL to WCAG guidance)",
"suggestion": "string (Suggestion for fixing the issue)",
"count": "number (Count of empty buttons without aria-label)",
"details": [
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (The full tag)",
"matchStartIndexInLine": "number"
}
]
}
},
"ariaElements": {
"ariaLabel": {
"suggestions": {
"empty": "string (Suggestion for empty aria-labels)",
"nonEmpty": "string (Suggestion for non-empty aria-labels)",
"wcagLink": "string (URL to WCAG guidance for ARIA naming)"
},
"total": "number (Total 'aria-label' attributes found)",
"counts": {
"empty": "number (Count of 'aria-label' attributes that are empty)",
"nonEmpty": "number (Count of 'aria-label' attributes with content)"
},
"details": {
"empty": [ // Array of objects for each empty aria-label
{
"lineNumber": "number (Line number in the HTML content)",
"fullLineContent": "string (The full original line of HTML)",
"matchedString": "string (The exact matched 'aria-label=\"\"' string)",
"matchStartIndexInLine": "number (Start index of matchedString within the trimmed line)"
}
// ... more items
],
"nonEmpty": [ // Array of objects for each non-empty aria-label
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (The exact matched 'aria-label=\"value\"' string)",
"matchStartIndexInLine": "number"
}
// ... more items
]
}
}
// Future ARIA elements might be added here
},
"altText": {
"suggestions": {
"missing": "string (Suggestion for missing alt text)",
"empty": "string (Suggestion for empty alt text)",
"nonEmpty": "string (Suggestion for non-empty alt text)",
"wcagLink": "string (URL to WCAG guidance for non-text content)"
},
"counts": {
"totalImagesProcessed": "number (Total <img> tags found)",
"missing": "number (Count of <img> tags missing an 'alt' attribute)",
"empty": "number (Count of <img> tags with an empty 'alt=\"\"' attribute)",
"nonEmpty": "number (Count of <img> tags with non-empty 'alt' text)"
},
"details": {
"missing": [ // Array of objects for each image missing alt text
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (The full <img ...> tag)",
"matchStartIndexInLine": "number"
}
// ... more items
],
"empty": [ // Array of objects for each image with empty alt text
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (The matched 'alt=\"\"' attribute part)",
"matchStartIndexInLine": "number"
}
// ... more items
],
"nonEmpty": [ // Array of objects for each image with non-empty alt text
{
"lineNumber": "number",
"fullLineContent": "string",
"matchedString": "string (The matched 'alt=\"value\"' attribute part or full img tag if specific alt match fails)",
"matchStartIndexInLine": "number"
}
// ... more items
]
}
}
// Other categories like altText follow a similar structure
}
}
}
Report Object Details:
summary: A human-readable summary of the scan findings.
issuesFound: Total number of critical issues identified.
categories: An object containing different categories of checks.
documentStructure.htmlLang: Checks for the lang attribute on the <html> tag.
missing: (Boolean) True if the lang attribute is missing.
wcagLink: (String) URL to relevant WCAG guidance.
suggestion: (String) A textual suggestion for addressing the issue.
details: (Array) If missing, contains details of the <html> tag.
interactiveElements.totalIssues: A sum of all issues found within the sub-categories of interactive elements.
interactiveElements.positiveTabindex: Identifies elements with tabindex > 0.
wcagLink: (String) URL to relevant WCAG guidance.
suggestion: (String) A textual suggestion for addressing the issue.
count: Number of such elements.
details: Array of objects, each including attributeValue.
interactiveElements.genericLinkText: Flags links with generic text (e.g., "click here").
wcagLink: (String) URL to relevant WCAG guidance.
suggestion: (String) A textual suggestion for addressing the issue.
count: Number of such links.
details: Array of objects, each including linkText.
interactiveElements.emptyButtons: Finds <button> elements without text or an aria-label.
wcagLink: (String) URL to relevant WCAG guidance.
suggestion: (String) A textual suggestion for addressing the issue.
count: Number of such buttons.
details: Array of objects.
ariaElements.ariaLabel: Analysis of aria-label attributes. Includes a suggestions object (with empty, nonEmpty, and wcagLink fields), total count, counts (empty, nonEmpty), and details for each.
altText: Analysis of alt attributes on <img> tags. Includes a suggestions object (with missing, empty, nonEmpty, and wcagLink fields), counts (totalImagesProcessed, missing, empty, nonEmpty), and details for each.
Detail Item Structure (common for items in details arrays):
lineNumber: Line number in the HTML.
fullLineContent: The full content of the line.
matchedString: The specific HTML string that matched the check.
matchStartIndexInLine: Starting index of matchedString within fullLineContent.
attributeValue: (String, specific to positiveTabindex) The value of the positive tabindex.
linkText: (String, specific to genericLinkText) The text content of the link.
Error Responses
Status Code
Condition
Response Body Example
400 Bad Request
htmlContent is missing or not a string.
{
"success": false,
"message": "htmlContent (string) is required in the request body."
}
500 Internal Server Error
An error occurred during the scan process itself.
{
"success": false,
"message": "Failed to scan htmlContent due to an internal server error.",
"report": { /* Minimal report structure with zeroed counts and empty details */ },
"error_details": "string (Error message, only present in development environment)"
}
500 Internal Server Error
An error occurred during JSON response preparation or sending.
{
"success": false,
"message": "Server error: Could not construct or send JSON response.",
"error_details": "string (Error message, only present in development environment)"
}