Overview

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:

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

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:

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)"
}

Status Endpoint: GET /status

Provides the operational status of the Scan API.

Request

Response (Success 200 OK)

{
    "status": "active",
    "service": "scan-api",
    "timestamp": "ISO_Date_String (e.g., 2023-10-27T10:00:00.000Z)"
}