Introduction
API do wyszukiwania deklaracji dostępności na stronach instytucji publicznych.
API umożliwia automatyczne wyszukiwanie deklaracji dostępności na stronach internetowych polskich instytucji publicznych.
## Główne funkcjonalności
- **Wyszukiwanie deklaracji** - automatyczne znajdowanie linków do deklaracji dostępności
- **Pobieranie treści stron** - z opcjonalnym renderowaniem JavaScript
- **Integracja z AI** - wykorzystanie sztucznej inteligencji do analizy treści
- **Pattern matching** - rozpoznawanie wzorców typowych dla deklaracji dostępności
## Dostępne strategie wyszukiwania
API wykorzystuje wielopoziomowe podejście do wyszukiwania:
1. **Pattern matching** - szukanie po wzorcach tekstowych i linkach
2. **AI analysis** - analiza treści przez model językowy (opcjonalne)
3. **JavaScript rendering** - renderowanie stron dynamicznych przez Playwright (opcjonalne)
Authenticating requests
This API is not authenticated.
Crawler API
Wyszukiwanie deklaracji dostępności
Endpoint automatycznie wyszukuje deklarację dostępności na podanej stronie internetowej. Wykorzystuje wielopoziomową strategię wyszukiwania:
- Pattern matching - szukanie według wzorcow tekstowych i linków
- AI analysis - analiza treści przez model językowy (opcjonalne)
- JavaScript rendering - renderowanie stron dynamicznych przez Playwright (opcjonalne)
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/find-declaration?url=https%3A%2F%2Fexample.gov.pl&domain_id=123&timeout=60&max_depth=2&use[]=ai&use[]=render_js&follow_redirects=1" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"url\": \"http:\\/\\/\",
\"domain_id\": 31,
\"timeout\": 14,
\"follow_redirects\": true,
\"use\": [
\"render_js\"
],
\"_\": 4,
\"exclude\": [
\"meta\"
],
\"save_to_temp_file\": true,
\"type\": \"page\",
\"max_depth\": 1
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/find-declaration"
);
const params = {
"url": "https://example.gov.pl",
"domain_id": "123",
"timeout": "60",
"max_depth": "2",
"use[0]": "ai",
"use[1]": "render_js",
"follow_redirects": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"url": "http:\/\/",
"domain_id": 31,
"timeout": 14,
"follow_redirects": true,
"use": [
"render_js"
],
"_": 4,
"exclude": [
"meta"
],
"save_to_temp_file": true,
"type": "page",
"max_depth": 1
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-declaration';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'query' => [
'url' => 'https://example.gov.pl',
'domain_id' => '123',
'timeout' => '60',
'max_depth' => '2',
'use[0]' => 'ai',
'use[1]' => 'render_js',
'follow_redirects' => '1',
],
'json' => [
'url' => 'http://',
'domain_id' => 31,
'timeout' => 14,
'follow_redirects' => true,
'use' => [
'render_js',
],
'_' => 4,
'exclude' => [
'meta',
],
'save_to_temp_file' => true,
'type' => 'page',
'max_depth' => 1,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-declaration'
payload = {
"url": "http:\/\/",
"domain_id": 31,
"timeout": 14,
"follow_redirects": true,
"use": [
"render_js"
],
"_": 4,
"exclude": [
"meta"
],
"save_to_temp_file": true,
"type": "page",
"max_depth": 1
}
params = {
'url': 'https://example.gov.pl',
'domain_id': '123',
'timeout': '60',
'max_depth': '2',
'use[0]': 'ai',
'use[1]': 'render_js',
'follow_redirects': '1',
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Znaleziono deklarację):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl",
"title": "Przykładowa Instytucja",
"links_count": 42,
"content_size": 15234
},
"dd": {
"found": true,
"url": "https://example.gov.pl/deklaracja-dostepnosci",
"title": "Deklaracja dostępności",
"score": 85,
"method": "pattern",
"search_level": 1,
"validation": {
"is_valid": true,
"has_required_elements": true,
"wcag_version": "2.1",
"conformance_level": "AA"
}
}
}
Example response (200, Nie znaleziono deklaracji):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl",
"title": "Przykładowa Instytucja",
"links_count": 42,
"content_size": 15234
},
"dd": {
"found": false,
"url": null,
"search_level": 2,
"pages_checked": 5,
"method": "exhaustive"
}
}
Example response (200):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl",
"final_url": "https://example.gov.pl",
"title": "Urząd Przykładowy - Strona główna",
"links_count": 47,
"content_size": 18432,
"fetch_time": 0.842,
"rendered_with": "http",
"meta": {
"description": "Oficjalna strona Urzędu Przykładowego",
"keywords": "urząd, instytucja publiczna, administracja"
}
},
"dd": {
"found": true,
"url": "https://example.gov.pl/deklaracja-dostepnosci",
"title": "Deklaracja dostępności",
"score": 92,
"method": "pattern",
"search_level": 1,
"pages_checked": 1,
"validation": {
"is_valid": true,
"has_required_elements": true,
"wcag_version": "2.1",
"conformance_level": "AA",
"elements_found": [
"status zgodności",
"data sporządzenia",
"dane kontaktowe",
"procedura skargowa"
]
},
"metadata": {
"publication_date": "2024-01-15",
"last_update": "2024-09-01",
"entity_name": "Urząd Przykładowy",
"contact_email": "dostepnosc@example.gov.pl"
}
}
}
Example response (200):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.com",
"final_url": "https://example.com",
"title": "Przykładowa Firma - Strona główna",
"links_count": 32,
"content_size": 12845,
"fetch_time": 0.523,
"rendered_with": "http",
"meta": {
"description": "Strona firmowa Example",
"keywords": "firma, usługi, przykład"
}
},
"dd": {
"found": false,
"url": null,
"search_level": 2,
"pages_checked": 8,
"method": "exhaustive",
"searched_urls": [
"https://example.com",
"https://example.com/kontakt",
"https://example.com/o-nas",
"https://example.com/polityka-prywatnosci",
"https://example.com/regulamin",
"https://example.com/dostepnosc",
"https://example.com/accessibility",
"https://example.com/deklaracja"
],
"potential_matches": [],
"reason": "Nie znaleziono strony zawierającej deklarację dostępności ani linków pasujących do wzorców"
}
}
Example response (422, Błąd walidacji):
{
"message": "The given data was invalid.",
"errors": {
"url": [
"URL jest wymagany",
"URL musi zaczynać się od http:// lub https://"
]
}
}
Example response (500, Błąd serwera):
{
"code": 500,
"status": "error",
"message": "Wystąpił błąd podczas przetwarzania żądania"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Pobieranie zawartości strony
Pobiera i analizuje zawartość strony internetowej z opcjonalnym renderowaniem JavaScript. Zwraca pełną treść strony wraz z wyodrębnionymi linkami i metadanymi.
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/fetch-page?url=https%3A%2F%2Fexample.gov.pl%2Fabout&timeout=30&use[]=render_js&follow_redirects=1" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"url\": \"https:\\/\\/\",
\"domain_id\": 42,
\"timeout\": 7,
\"follow_redirects\": true,
\"use\": [
\"render_js\"
],
\"_\": 10,
\"exclude\": [
\"links\"
],
\"save_to_temp_file\": false,
\"type\": \"page\"
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/fetch-page"
);
const params = {
"url": "https://example.gov.pl/about",
"timeout": "30",
"use[0]": "render_js",
"follow_redirects": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"url": "https:\/\/",
"domain_id": 42,
"timeout": 7,
"follow_redirects": true,
"use": [
"render_js"
],
"_": 10,
"exclude": [
"links"
],
"save_to_temp_file": false,
"type": "page"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/fetch-page';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'query' => [
'url' => 'https://example.gov.pl/about',
'timeout' => '30',
'use[0]' => 'render_js',
'follow_redirects' => '1',
],
'json' => [
'url' => 'https://',
'domain_id' => 42,
'timeout' => 7,
'follow_redirects' => true,
'use' => [
'render_js',
],
'_' => 10,
'exclude' => [
'links',
],
'save_to_temp_file' => false,
'type' => 'page',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/fetch-page'
payload = {
"url": "https:\/\/",
"domain_id": 42,
"timeout": 7,
"follow_redirects": true,
"use": [
"render_js"
],
"_": 10,
"exclude": [
"links"
],
"save_to_temp_file": false,
"type": "page"
}
params = {
'url': 'https://example.gov.pl/about',
'timeout': '30',
'use[0]': 'render_js',
'follow_redirects': '1',
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Sukces):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl/about",
"final_url": "https://example.gov.pl/o-nas",
"title": "O nas - Przykładowa Instytucja",
"content": "<html>...</html>",
"links": [
{
"url": "https://example.gov.pl/kontakt",
"text": "Kontakt",
"title": "Skontaktuj się z nami"
},
{
"url": "https://example.gov.pl/deklaracja-dostepnosci",
"text": "Deklaracja dostępności"
}
],
"meta": {
"description": "Informacje o naszej instytucji",
"keywords": "instytucja publiczna, urząd"
},
"rendered_with": "playwright",
"fetch_time": 1.234
}
}
Example response (200):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl/o-nas",
"final_url": "https://example.gov.pl/o-nas",
"title": "O nas - Urząd Przykładowy",
"content": "<!DOCTYPE html>\n<html lang=\"pl\">\n<head>\n <meta charset=\"UTF-8\">\n <title>O nas - Urząd Przykładowy</title>\n <meta name=\"description\" content=\"Informacje o Urzędzie Przykładowym\">\n</head>\n<body>\n <header>\n <h1>Urząd Przykładowy</h1>\n <nav>\n <ul>\n <li><a href=\"/\">Strona główna</a></li>\n <li><a href=\"/o-nas\">O nas</a></li>\n <li><a href=\"/kontakt\">Kontakt</a></li>\n <li><a href=\"/deklaracja-dostepnosci\">Deklaracja dostępności</a></li>\n </ul>\n </nav>\n </header>\n <main>\n <h2>O Urzędzie</h2>\n <p>Urząd Przykładowy jest jednostką administracji publicznej...</p>\n </main>\n <footer>\n <p>© 2024 Urząd Przykładowy</p>\n </footer>\n</body>\n</html>",
"links": [
{
"url": "https://example.gov.pl/",
"text": "Strona główna",
"title": null,
"alt": null
},
{
"url": "https://example.gov.pl/o-nas",
"text": "O nas",
"title": null,
"alt": null
},
{
"url": "https://example.gov.pl/kontakt",
"text": "Kontakt",
"title": null,
"alt": null
},
{
"url": "https://example.gov.pl/deklaracja-dostepnosci",
"text": "Deklaracja dostępności",
"title": null,
"alt": null
}
],
"meta": {
"description": "Informacje o Urzędzie Przykładowym",
"charset": "UTF-8",
"viewport": "width=device-width, initial-scale=1.0"
},
"rendered_with": "playwright",
"fetch_time": 2.156,
"content_type": "text/html; charset=UTF-8",
"status_code": 200
}
}
Example response (404, Strona nie istnieje):
{
"code": 404,
"status": "error",
"message": "Nie można pobrać strony: 404 Not Found"
}
Example response (422, Błąd walidacji):
{
"message": "The given data was invalid.",
"errors": {
"url": [
"URL jest wymagany"
]
}
}
Example response (500, Błąd serwera):
{
"code": 500,
"status": "error",
"message": "Wystąpił błąd podczas pobierania strony"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Analiza dostępności (WCAG/A11y) strony
Endpoint analizuje dostępność cyfrową strony internetowej za pomocą axe-core. Zwraca naruszenia WCAG, testy które przeszły oraz elementy wymagające manualnej weryfikacji. Analiza wykonywana jest zawsze w przeglądarce (Playwright) dla maksymalnej dokładności.
Metody HTTP
- GET - dla prostych zapytań z URL (query params)
- POST - dla zaawansowanych zapytań (body params)
Parametry array
- Array syntax:
?tags[]=wcag2aa&tags[]=wcag21aalub?tags=wcag2aa(auto-normalizacja) - W POST:
{"tags": ["wcag2aa", "wcag21aa"]}
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/scan-accessibility?url=https%3A%2F%2Fexample.gov.pl&domain_id=123&use[]=smart_fetch&use[]=ai&timeout=30&include=&tags=&save_to_temp_file=1&type=page" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"url\": \"http:\\/\\/\",
\"domain_id\": 17,
\"timeout\": 23,
\"follow_redirects\": true,
\"use\": [
\"render_js\"
],
\"_\": 18,
\"exclude\": [
\"content\"
],
\"save_to_temp_file\": true,
\"type\": \"hp\",
\"include\": [
\"passes\"
],
\"tags\": [
\"best-practice\"
]
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/scan-accessibility"
);
const params = {
"url": "https://example.gov.pl",
"domain_id": "123",
"use[0]": "smart_fetch",
"use[1]": "ai",
"timeout": "30",
"include": "",
"tags": "",
"save_to_temp_file": "1",
"type": "page",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"url": "http:\/\/",
"domain_id": 17,
"timeout": 23,
"follow_redirects": true,
"use": [
"render_js"
],
"_": 18,
"exclude": [
"content"
],
"save_to_temp_file": true,
"type": "hp",
"include": [
"passes"
],
"tags": [
"best-practice"
]
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/scan-accessibility';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'query' => [
'url' => 'https://example.gov.pl',
'domain_id' => '123',
'use[0]' => 'smart_fetch',
'use[1]' => 'ai',
'timeout' => '30',
'include' => '',
'tags' => '',
'save_to_temp_file' => '1',
'type' => 'page',
],
'json' => [
'url' => 'http://',
'domain_id' => 17,
'timeout' => 23,
'follow_redirects' => true,
'use' => [
'render_js',
],
'_' => 18,
'exclude' => [
'content',
],
'save_to_temp_file' => true,
'type' => 'hp',
'include' => [
'passes',
],
'tags' => [
'best-practice',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/scan-accessibility'
payload = {
"url": "http:\/\/",
"domain_id": 17,
"timeout": 23,
"follow_redirects": true,
"use": [
"render_js"
],
"_": 18,
"exclude": [
"content"
],
"save_to_temp_file": true,
"type": "hp",
"include": [
"passes"
],
"tags": [
"best-practice"
]
}
params = {
'url': 'https://example.gov.pl',
'domain_id': '123',
'use[0]': 'smart_fetch',
'use[1]': 'ai',
'timeout': '30',
'include': '',
'tags': '',
'save_to_temp_file': '1',
'type': 'page',
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Znaleziono naruszenia):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl",
"final_url": "https://example.gov.pl",
"code": 200,
"content_type": "text/html",
"speed": 1.234,
"a11y": {
"success": true,
"results": {
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Elements must have sufficient color contrast"
}
]
},
"url": "https://example.gov.pl",
"timestamp": "2025-09-30T12:00:00Z"
}
}
}
Example response (200, Brak naruszeń):
{
"code": 200,
"status": "success",
"page": {
"url": "https://example.gov.pl",
"code": 200,
"a11y": {
"success": true,
"results": {
"violations": []
},
"url": "https://example.gov.pl"
}
}
}
Example response (200):
{
"code": 200,
"status": "success",
"page": {
"domain_id": null,
"url": "https://example.gov.pl",
"final_url": "https://example.gov.pl",
"code": 200,
"status": "OK",
"content": null,
"content_type": "text/html; charset=UTF-8",
"content_size": 15234,
"content_temp_file": "/tmp/crawler_html_abc123",
"content_archive_file": null,
"links": [],
"speed": 1.234,
"error": null,
"ip": "93.184.216.34",
"score": null,
"screenshot": null,
"client": "Laravel/Http",
"type": "page",
"dd": {
"content": null,
"raport": null
},
"a11y": {
"success": true,
"results": {
"violations": [
{
"id": "html-has-lang",
"impact": "serious",
"tags": [
"cat.language",
"wcag2a",
"wcag311",
"ACT"
],
"description": "Ensure every HTML document has a lang attribute",
"help": "<html> element must have a lang attribute",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-has-lang?application=playwright",
"nodes": [
{
"html": "<html>",
"target": [
"html"
],
"failureSummary": "Fix any of the following:\n The <html> element does not have a lang attribute"
}
]
},
{
"id": "image-alt",
"impact": "critical",
"tags": [
"cat.text-alternatives",
"wcag2a",
"wcag111",
"section508",
"ACT"
],
"description": "Ensure <img> elements have alternative text or a role of none or presentation",
"help": "Images must have alternative text",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/image-alt?application=playwright",
"nodes": [
{
"html": "<img src=\"logo.jpg\">",
"target": [
"img"
],
"failureSummary": "Fix any of the following:\n Element does not have an alt attribute"
}
]
},
{
"id": "color-contrast",
"impact": "serious",
"tags": [
"cat.color",
"wcag2aa",
"wcag143"
],
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"help": "Elements must meet minimum color contrast ratio thresholds",
"helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=playwright",
"nodes": [
{
"html": "<a href=\"/contact\" style=\"color: #ccc; background: #fff;\">Kontakt</a>",
"target": [
"a[href=\"/contact\"]"
],
"failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 2.5 (foreground color: #cccccc, background color: #ffffff, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
}
]
}
]
},
"url": "https://example.gov.pl",
"timestamp": "2025-09-30T18:00:00.000Z",
"testEngine": {
"name": "axe-core",
"version": "4.10.3"
},
"ai_analysis": {
"analyzed_violations": [
{
"violation_id": "html-has-lang",
"human_description": "Strona nie posiada atrybutu 'lang' w elemencie <html>, który informuje przeglądarki i technologie asystujące o języku strony. Użytkownicy korzystający z czytników ekranu mogą mieć problem z poprawnym odczytaniem treści.",
"severity": "poważny",
"affected_elements": 1,
"recommendation": "Dodaj atrybut lang do tagu <html>, np. <html lang='pl'> dla strony w języku polskim. To pomoże czytnikowi ekranu wybrać odpowiednią wymowę i akcent."
},
{
"violation_id": "color-contrast",
"human_description": "Link ma zbyt niski kontrast między tekstem a tłem (2.5:1), podczas gdy minimum dla WCAG 2.0 AA to 4.5:1. Użytkownicy z problemami ze wzrokiem mogą mieć trudność z odczytaniem tego linku.",
"severity": "poważny",
"affected_elements": 1,
"recommendation": "Zmień kolor tekstu z #ccc (jasnoszary) na ciemniejszy, aby osiągnąć kontrast minimum 4.5:1. Możesz użyć narzędzi online do sprawdzenia kontrastu kolorów."
}
],
"total_analyzed": 2,
"analysis_timestamp": "2025-09-30T18:05:00.000Z"
}
}
}
}
Example response (200):
{
"code": 200,
"status": "success",
"page": {
"domain_id": null,
"url": "https://example.gov.pl",
"final_url": "https://example.gov.pl",
"code": 200,
"status": "OK",
"content": null,
"content_type": "text/html; charset=UTF-8",
"content_size": 12456,
"content_temp_file": "/tmp/crawler_html_xyz789",
"content_archive_file": null,
"links": [],
"speed": 0.987,
"error": null,
"ip": "93.184.216.34",
"score": null,
"screenshot": null,
"client": "Laravel/Http",
"type": "page",
"dd": {
"content": null,
"raport": null
},
"a11y": {
"success": true,
"results": {
"violations": []
},
"url": "https://example.gov.pl",
"timestamp": "2025-09-30T18:00:00.000Z",
"testEngine": {
"name": "axe-core",
"version": "4.10.3"
}
}
}
}
Example response (422, Błąd walidacji):
{
"success": false,
"message": "Validation errors",
"errors": {
"url": [
"URL jest wymagany"
]
}
}
Example response (500, Błąd serwera):
{
"code": 500,
"status": "error",
"message": "Failed to analyze accessibility",
"error": "Playwright not available"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Zbieranie linków ze strony (asynchroniczne)
Endpoint inicjalizuje asynchroniczne zadanie zbierania linków ze strony. Zwraca job_id i URL do sprawdzania statusu zadania.
Crawler zawsze przechodzi przez wszystkie linki, różnica parametru 'type' polega tylko na tym, które zasoby są zapisywane do wyników (filtrowanie po Content-Type z HTTP response).
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/collect-links?url=https%3A%2F%2Fexample.gov.pl&max_depth=3&collect=external&type=attachment&max_execution_time=600&use[]=render_js&timeout=60" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"url\": \"https:\\/\\/\",
\"domain_id\": 20,
\"timeout\": 12,
\"follow_redirects\": false,
\"use\": [
\"ai\"
],
\"_\": 8,
\"exclude\": [
\"content\"
],
\"save_to_temp_file\": false,
\"type\": \"all\",
\"max_depth\": 2,
\"collect\": \"external\",
\"max_execution_time\": 15
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/collect-links"
);
const params = {
"url": "https://example.gov.pl",
"max_depth": "3",
"collect": "external",
"type": "attachment",
"max_execution_time": "600",
"use[0]": "render_js",
"timeout": "60",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"url": "https:\/\/",
"domain_id": 20,
"timeout": 12,
"follow_redirects": false,
"use": [
"ai"
],
"_": 8,
"exclude": [
"content"
],
"save_to_temp_file": false,
"type": "all",
"max_depth": 2,
"collect": "external",
"max_execution_time": 15
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/collect-links';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'query' => [
'url' => 'https://example.gov.pl',
'max_depth' => '3',
'collect' => 'external',
'type' => 'attachment',
'max_execution_time' => '600',
'use[0]' => 'render_js',
'timeout' => '60',
],
'json' => [
'url' => 'https://',
'domain_id' => 20,
'timeout' => 12,
'follow_redirects' => false,
'use' => [
'ai',
],
'_' => 8,
'exclude' => [
'content',
],
'save_to_temp_file' => false,
'type' => 'all',
'max_depth' => 2,
'collect' => 'external',
'max_execution_time' => 15,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/collect-links'
payload = {
"url": "https:\/\/",
"domain_id": 20,
"timeout": 12,
"follow_redirects": false,
"use": [
"ai"
],
"_": 8,
"exclude": [
"content"
],
"save_to_temp_file": false,
"type": "all",
"max_depth": 2,
"collect": "external",
"max_execution_time": 15
}
params = {
'url': 'https://example.gov.pl',
'max_depth': '3',
'collect': 'external',
'type': 'attachment',
'max_execution_time': '600',
'use[0]': 'render_js',
'timeout': '60',
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200):
{
"job_id": "abc123def456",
"status": "pending",
"params": {
"url": "https://example.gov.pl",
"max_depth": 3,
"collect": "external",
"type": "html",
"max_execution_time": 300,
"use": [
"render_js"
],
"timeout": 30
},
"status_url": "/api/collect-links/status/abc123def456",
"created_at": "2025-10-01 10:00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Sprawdzanie statusu zadania zbierania linków
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/collect-links/status/abc123def456" \
--header "Accept: application/json" \
--header "Content-Type: application/json"const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/collect-links/status/abc123def456"
);
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/collect-links/status/abc123def456';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/collect-links/status/abc123def456'
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Pending):
{
"job_id": "abc123def456",
"status": "pending",
"params": {
"url": "https://example.gov.pl",
"max_depth": 3
},
"created_at": "2025-10-01 10:00:00"
}
Example response (200, Completed):
{
"job_id": "abc123def456",
"status": "completed",
"params": {
"url": "https://example.gov.pl",
"max_depth": 3
},
"result": {
"total_links": 234,
"links": [
"https://external.com",
"https://external2.com"
]
},
"completed_at": "2025-10-01 10:02:15",
"execution_time": 135.2
}
Example response (200, Failed):
{
"job_id": "abc123def456",
"status": "failed",
"params": {
"url": "https://example.gov.pl"
},
"error": "Timeout exceeded",
"failed_at": "2025-10-01 10:05:00",
"execution_time": 300
}
Example response (404):
{
"message": "Job not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Lista wszystkich jobów asynchronicznych
Endpoint zwraca listę wszystkich jobów (collect-links) z możliwością filtrowania po statusie. Joby są sortowane po dacie utworzenia (najnowsze pierwsze).
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/jobs?status=completed" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"status\": \"pending\"
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/jobs"
);
const params = {
"status": "completed",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"status": "pending"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/jobs';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'query' => [
'status' => 'completed',
],
'json' => [
'status' => 'pending',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/jobs'
payload = {
"status": "pending"
}
params = {
'status': 'completed',
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Lista wszystkich jobów):
{
"total": 156,
"jobs": [
{
"job_id": "abc123-def456",
"status": "completed",
"status_url": "/api/collect-links/status/abc123-def456",
"params": {
"url": "https://wolka.pl",
"max_depth": 3,
"collect": "external",
"max_execution_time": 300,
"use": [
"render_js"
],
"timeout": 30,
"created_at": "2025-10-02 09:42:41"
},
"completed_at": "2025-10-02 09:42:55",
"execution_time": 14.2
}
]
}
Example response (200, Tylko joby pending):
{
"total": 3,
"jobs": [
{
"job_id": "xyz789",
"status": "pending",
"status_url": "/api/collect-links/status/xyz789",
"params": {
"url": "https://example.com",
"max_depth": 2,
"collect": "internal",
"max_execution_time": 300,
"use": [],
"timeout": 30,
"created_at": "2025-10-02 12:30:15"
}
}
]
}
Example response (422, Błąd walidacji):
{
"message": "The given data was invalid.",
"errors": {
"status": [
"Dozwolone wartości dla status to: pending, completed, failed, all"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Wyszukiwanie reprezentatywnych próbek stron dla audytu WCAG
Automatycznie wyszukuje reprezentatywne próbki stron (samples) dla audytu dostępności cyfrowej zgodnie z metodologią WCAG-EM. Wykorzystuje AI do inteligentnej identyfikacji typów stron.
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/find-samples?url=https%3A%2F%2Fexample.gov.pl&sample_types[]=contact_form&sample_types[]=article&sample_types[]=gallery&max_depth=3&max_execution_time=600&timeout=30&use[]=ai&domain_id=123" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"url\": \"https:\\/\\/\",
\"domain_id\": 14,
\"timeout\": 13,
\"follow_redirects\": true,
\"use\": [
\"ai\"
],
\"_\": 17,
\"exclude\": [
\"links\"
],
\"save_to_temp_file\": true,
\"type\": \"link\",
\"sample_types\": [
\"video_audio\"
],
\"max_depth\": 2,
\"max_execution_time\": 600,
\"use[]\": [
\"ai\",
\"render_js\"
],
\"sample_types[]\": [
\"home\",
\"contact_form\",
\"search\"
]
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/find-samples"
);
const params = {
"url": "https://example.gov.pl",
"sample_types[0]": "contact_form",
"sample_types[1]": "article",
"sample_types[2]": "gallery",
"max_depth": "3",
"max_execution_time": "600",
"timeout": "30",
"use[0]": "ai",
"domain_id": "123",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"url": "https:\/\/",
"domain_id": 14,
"timeout": 13,
"follow_redirects": true,
"use": [
"ai"
],
"_": 17,
"exclude": [
"links"
],
"save_to_temp_file": true,
"type": "link",
"sample_types": [
"video_audio"
],
"max_depth": 2,
"max_execution_time": 600,
"use[]": [
"ai",
"render_js"
],
"sample_types[]": [
"home",
"contact_form",
"search"
]
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-samples';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'query' => [
'url' => 'https://example.gov.pl',
'sample_types[0]' => 'contact_form',
'sample_types[1]' => 'article',
'sample_types[2]' => 'gallery',
'max_depth' => '3',
'max_execution_time' => '600',
'timeout' => '30',
'use[0]' => 'ai',
'domain_id' => '123',
],
'json' => [
'url' => 'https://',
'domain_id' => 14,
'timeout' => 13,
'follow_redirects' => true,
'use' => [
'ai',
],
'_' => 17,
'exclude' => [
'links',
],
'save_to_temp_file' => true,
'type' => 'link',
'sample_types' => [
'video_audio',
],
'max_depth' => 2,
'max_execution_time' => 600,
'use[]' => [
'ai',
'render_js',
],
'sample_types[]' => [
'home',
'contact_form',
'search',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-samples'
payload = {
"url": "https:\/\/",
"domain_id": 14,
"timeout": 13,
"follow_redirects": true,
"use": [
"ai"
],
"_": 17,
"exclude": [
"links"
],
"save_to_temp_file": true,
"type": "link",
"sample_types": [
"video_audio"
],
"max_depth": 2,
"max_execution_time": 600,
"use[]": [
"ai",
"render_js"
],
"sample_types[]": [
"home",
"contact_form",
"search"
]
}
params = {
'url': 'https://example.gov.pl',
'sample_types[0]': 'contact_form',
'sample_types[1]': 'article',
'sample_types[2]': 'gallery',
'max_depth': '3',
'max_execution_time': '600',
'timeout': '30',
'use[0]': 'ai',
'domain_id': '123',
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Job zainicjalizowany):
{
"code": 200,
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status_url": "https://api.example.com/api/find-samples/status/550e8400-e29b-41d4-a716-446655440000",
"params": {
"url": "https://example.gov.pl",
"sample_types": [
"homepage",
"contact_form",
"article"
],
"max_depth": 2,
"max_execution_time": 600
}
}
Example response (200):
{
"code": 200,
"status": "success",
"message": "Job find-samples został utworzony i uruchomiony",
"job_id": "9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b",
"status_url": "/api/find-samples/status/9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b",
"data": {
"url": "https://example.gov.pl",
"sample_types": [
"home",
"contact_form",
"search",
"sitemap",
"login"
],
"max_depth": 2,
"max_execution_time": 600,
"use": [
"ai",
"render_js"
]
}
}
Example response (422, Błąd walidacji):
{
"message": "The given data was invalid.",
"errors": {
"sample_types": [
"Nieznany typ próbki"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Status zadania find-samples
Sprawdza status zadania wyszukiwania próbek stron. Zwraca progress i znalezione próbki.
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/status/sed" \
--header "Accept: application/json" \
--header "Content-Type: application/json"const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/status/sed"
);
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/status/sed';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/status/sed'
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Job w trakcie):
{
"code": 200,
"status": "processing",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"progress": {
"total": 10,
"found": 3,
"remaining": 7
},
"samples": {
"homepage": {
"url": "https://example.gov.pl",
"found": true,
"confidence": "high",
"reason": "Strona główna"
},
"contact_form": {
"url": "https://example.gov.pl/kontakt",
"found": true,
"confidence": "high",
"reason": "Formularz kontaktowy"
},
"article": {
"url": null,
"found": false
}
}
}
Example response (200, Job zakończony):
{
"code": 200,
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"progress": {
"total": 10,
"found": 8,
"remaining": 2
},
"samples": {}
}
Example response (200):
{
"code": 200,
"status": "success",
"job_id": "9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b",
"job_status": "completed",
"progress": {
"current": 12,
"total": 12,
"percentage": 100
},
"samples": {
"home": {
"found": true,
"url": "https://example.gov.pl",
"title": "Urząd Przykładowy - Strona główna",
"confidence": "high",
"screenshot": "/api/find-samples/9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b/screenshot/home"
},
"contact_form": {
"found": true,
"url": "https://example.gov.pl/kontakt",
"title": "Kontakt - Urząd Przykładowy",
"confidence": "high",
"screenshot": "/api/find-samples/9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b/screenshot/contact_form"
},
"search": {
"found": true,
"url": "https://example.gov.pl/wyszukiwarka",
"title": "Wyszukiwarka - Urząd Przykładowy",
"confidence": "high",
"screenshot": "/api/find-samples/9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b/screenshot/search"
},
"sitemap": {
"found": true,
"url": "https://example.gov.pl/mapa-strony",
"title": "Mapa strony - Urząd Przykładowy",
"confidence": "medium",
"screenshot": "/api/find-samples/9d4e8c2a-1b3f-4d5e-8f9a-2c3d4e5f6a7b/screenshot/sitemap"
},
"login": {
"found": false,
"url": null,
"title": null,
"confidence": null,
"screenshot": null
}
},
"stats": {
"found_count": 4,
"not_found_count": 1,
"pages_analyzed": 12,
"execution_time": 45.3
}
}
Example response (404, Job nie znaleziony):
{
"code": 404,
"status": "error",
"message": "Job not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Pobierz screenshot próbki
Zwraca plik PNG ze screenshotem znalezionej próbki. Endpoint publiczny - nie wymaga autentykacji (job_id = UUID, trudny do zgadnięcia).
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/in/screenshot/consequatur" \
--header "Accept: application/json" \
--header "Content-Type: application/json"const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/in/screenshot/consequatur"
);
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/in/screenshot/consequatur';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/find-samples/in/screenshot/consequatur'
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Screenshot znaleziony):
[binary PNG file]
Example response (404, Screenshot nie istnieje):
{
"code": 404,
"status": "error",
"message": "Screenshot not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Pobierz dostępne typy próbek z konfiguracji
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/sample-types" \
--header "Accept: application/json" \
--header "Content-Type: application/json"const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/sample-types"
);
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/sample-types';
$response = $client->get(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/sample-types'
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (404):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "The route api/sample-types could not be found."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
A11Y FastScan
A11Y FASTSCAN - Comprehensive accessibility audit
Comprehensive accessibility audit combining:
- find-samples - finding representative page samples
- scan-accessibility - axe-core analysis per sample
- AI aggregate - violations aggregation + change scale assessment
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan?url=https%3A%2F%2Fwolka.pl&use%5B%5D=&sample_types%5B%5D=&max_depth=3&max_execution_time=600&timeout=30&domain_id=1" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"url\": \"https:\\/\\/wolka.pl\",
\"domain_id\": 1,
\"timeout\": 30,
\"follow_redirects\": true,
\"use\": [
\"smart_fetch\"
],
\"_\": 18,
\"sample_types\": [
\"article\"
],
\"max_depth\": 3,
\"max_execution_time\": 600,
\"use[]\": [
\"ai\",
\"render_js\"
],
\"sample_types[]\": [
\"homepage\",
\"contact_form\",
\"article\"
]
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan"
);
const params = {
"url": "https://wolka.pl",
"use[]": "",
"sample_types[]": "",
"max_depth": "3",
"max_execution_time": "600",
"timeout": "30",
"domain_id": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"url": "https:\/\/wolka.pl",
"domain_id": 1,
"timeout": 30,
"follow_redirects": true,
"use": [
"smart_fetch"
],
"_": 18,
"sample_types": [
"article"
],
"max_depth": 3,
"max_execution_time": 600,
"use[]": [
"ai",
"render_js"
],
"sample_types[]": [
"homepage",
"contact_form",
"article"
]
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'url' => 'https://wolka.pl',
'use[]' => '',
'sample_types[]' => '',
'max_depth' => '3',
'max_execution_time' => '600',
'timeout' => '30',
'domain_id' => '1',
],
'json' => [
'url' => 'https://wolka.pl',
'domain_id' => 1,
'timeout' => 30,
'follow_redirects' => true,
'use' => [
'smart_fetch',
],
'_' => 18,
'sample_types' => [
'article',
],
'max_depth' => 3,
'max_execution_time' => 600,
'use[]' => [
'ai',
'render_js',
],
'sample_types[]' => [
'homepage',
'contact_form',
'article',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan'
payload = {
"url": "https:\/\/wolka.pl",
"domain_id": 1,
"timeout": 30,
"follow_redirects": true,
"use": [
"smart_fetch"
],
"_": 18,
"sample_types": [
"article"
],
"max_depth": 3,
"max_execution_time": 600,
"use[]": [
"ai",
"render_js"
],
"sample_types[]": [
"homepage",
"contact_form",
"article"
]
}
params = {
'url': 'https://wolka.pl',
'use[]': '',
'sample_types[]': '',
'max_depth': '3',
'max_execution_time': '600',
'timeout': '30',
'domain_id': '1',
}
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Job created):
{
"code": 200,
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status_url": "https://crawler.deklaracja-dostepnosci.info/api/a11y-fastscan/status/550e8400-e29b-41d4-a716-446655440000"
}
Example response (200):
{
"code": 200,
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status_url": "https://crawler.deklaracja-dostepnosci.info/api/a11y-fastscan/status/550e8400-e29b-41d4-a716-446655440000",
"message": "Audyt dostępności został zainicjowany. Użyj status_url aby monitorować postęp."
}
Example response (422, Validation error):
{
"code": 422,
"status": "error",
"message": "Invalid parameters",
"errors": {
"url": [
"The url field is required."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get a11y-fastscan job status with partial/full report
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/status/550e8400-e29b-41d4-a716-446655440000" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/status/550e8400-e29b-41d4-a716-446655440000"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/status/550e8400-e29b-41d4-a716-446655440000';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/status/550e8400-e29b-41d4-a716-446655440000'
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Job completed):
{
"code": 200,
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"progress": {
"phase": "completed",
"current_step": 4,
"total_steps": 4,
"percentage": 100
},
"report": {
"summary": {},
"violations_by_type": [],
"pages_analyzed": []
}
}
Example response (200, Job processing):
{
"code": 200,
"status": "processing",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"progress": {
"phase": "scanning_samples",
"current_step": 2,
"total_steps": 4,
"percentage": 50,
"current_sample": 3,
"total_samples": 8
}
}
Example response (200, Job processing):
{
"code": 200,
"status": "processing",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"progress": {
"phase": "scanning_samples",
"current_step": 2,
"total_steps": 4,
"percentage": 50,
"current_sample": 3,
"total_samples": 8,
"sample_type": "contact_form",
"sample_url": "https://example.com/kontakt"
},
"message": "Audyt w trakcie realizacji. Aktualna faza: skanowanie próbek."
}
Example response (200, Job completed):
{
"code": 200,
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"progress": {
"phase": "completed",
"current_step": 4,
"total_steps": 4,
"percentage": 100
},
"report": {
"summary": {
"total_pages_scanned": 8,
"pages_with_violations": 7,
"total_violations": 45,
"unique_violation_types": 12,
"severity_distribution": {
"critical": 3,
"serious": 15,
"moderate": 20,
"minor": 7
},
"change_scale": "moderate",
"estimated_effort": "Umiarkowany - wymagane zmiany w HTML i stylach CSS. Część problemów można rozwiązać globalnie poprzez aktualizację stylów, inne wymagają modyfikacji struktury formularzy i nawigacji."
},
"violations_by_type": [
{
"violation_id": "color-contrast",
"priority": "HIGH",
"severity": "serious",
"total_occurrences": 12,
"pages_affected": [
"https://example.com/",
"https://example.com/kontakt",
"https://example.com/aktualnosci",
"https://example.com/uslugi",
"https://example.com/o-nas",
"https://example.com/galeria"
],
"is_systemic": true,
"sample_types_affected": [
"homepage",
"contact_form",
"article",
"gallery",
"accessibility_statement",
"search_form"
],
"description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
"help": "Elements must meet minimum color contrast ratio thresholds",
"help_url": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=playwright",
"human_description": "Zbyt niski kontrast między tekstem a tłem utrudnia czytanie treści, szczególnie osobom z problemami ze wzrokiem. Problem występuje w wielu miejscach na stronie, głównie w nawigacji głównej i stopce.",
"recommendation": "Zmień kolory w globalnych stylach CSS tak, aby kontrast między tekstem a tłem wynosił co najmniej 4.5:1 dla normalnego tekstu i 3:1 dla dużego tekstu (18px bold lub 24px+). Sprawdź kolory za pomocą narzędzia kontrastu WCAG.",
"fix_effort": "minor"
},
{
"violation_id": "label",
"priority": "HIGH",
"severity": "serious",
"total_occurrences": 8,
"pages_affected": [
"https://example.com/kontakt",
"https://example.com/szukaj"
],
"is_systemic": false,
"sample_types_affected": [
"contact_form",
"search_form"
],
"description": "Ensure every form element has a label",
"help": "Form elements must have labels",
"help_url": "https://dequeuniversity.com/rules/axe/4.10/label?application=playwright",
"human_description": "Pola formularzy nie mają etykiet <label> powiązanych z polami <input>. To uniemożliwia czytnikowi ekranu prawidłowe ogłoszenie pola i utrudnia wypełnienie formularza osobom niewidomym.",
"recommendation": "Dla każdego pola <input>, <select>, <textarea> dodaj odpowiednią etykietę <label> z atrybutem 'for' wskazującym na 'id' pola. Alternatywnie użyj aria-label lub aria-labelledby dla pól bez widocznej etykiety.",
"fix_effort": "moderate"
},
{
"violation_id": "landmark-one-main",
"priority": "MEDIUM",
"severity": "moderate",
"total_occurrences": 8,
"pages_affected": [
"https://example.com/",
"https://example.com/kontakt",
"https://example.com/aktualnosci",
"https://example.com/uslugi",
"https://example.com/o-nas",
"https://example.com/galeria",
"https://example.com/deklaracja-dostepnosci",
"https://example.com/szukaj"
],
"is_systemic": true,
"sample_types_affected": [
"homepage",
"contact_form",
"article",
"gallery",
"accessibility_statement",
"search_form",
"data_table",
"interactive_elements"
],
"description": "Ensure every page has a main landmark",
"help": "Document must have one main landmark",
"help_url": "https://dequeuniversity.com/rules/axe/4.10/landmark-one-main?application=playwright",
"human_description": "Strony nie mają oznaczonego głównego obszaru treści (landmark <main>). To utrudnia osobom używającym czytników ekranu szybką nawigację do głównej treści strony.",
"recommendation": "Obuduj główną treść każdej strony w tag <main> lub dodaj role='main' do głównego kontenera. Upewnij się, że jest tylko jeden <main> na stronie i nie zawiera powtarzalnych elementów jak nawigacja czy stopka.",
"fix_effort": "minor"
},
{
"violation_id": "region",
"priority": "LOW",
"severity": "moderate",
"total_occurrences": 5,
"pages_affected": [
"https://example.com/",
"https://example.com/aktualnosci",
"https://example.com/galeria"
],
"is_systemic": false,
"sample_types_affected": [
"homepage",
"article",
"gallery"
],
"description": "Ensure all page content is contained by landmarks",
"help": "All page content should be contained by landmarks",
"help_url": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright",
"human_description": "Część treści strony znajduje się poza semantycznymi obszarami (landmarks) jak <main>, <nav>, <aside>. To utrudnia nawigację czytników ekranu.",
"recommendation": "Upewnij się, że cała widoczna treść jest zawarta w odpowiednich landmarkach HTML5: <header>, <nav>, <main>, <aside>, <footer> lub użyj odpowiednich ról ARIA.",
"fix_effort": "minor"
}
],
"pages_analyzed": [
{
"sample_type": "homepage",
"url": "https://example.com/",
"violations_count": 8,
"screenshot": "/api/find-samples/550e8400-e29b-41d4-a716-446655440000/screenshot/homepage"
},
{
"sample_type": "contact_form",
"url": "https://example.com/kontakt",
"violations_count": 12,
"screenshot": "/api/find-samples/550e8400-e29b-41d4-a716-446655440000/screenshot/contact_form"
},
{
"sample_type": "article",
"url": "https://example.com/aktualnosci/otwarcie-nowego-oddzialu",
"violations_count": 5,
"screenshot": "/api/find-samples/550e8400-e29b-41d4-a716-446655440000/screenshot/article"
},
{
"sample_type": "gallery",
"url": "https://example.com/galeria",
"violations_count": 6,
"screenshot": "/api/find-samples/550e8400-e29b-41d4-a716-446655440000/screenshot/gallery"
},
{
"sample_type": "accessibility_statement",
"url": "https://example.com/deklaracja-dostepnosci",
"violations_count": 3,
"screenshot": "/api/find-samples/550e8400-e29b-41d4-a716-446655440000/screenshot/accessibility_statement"
},
{
"sample_type": "search_form",
"url": "https://example.com/szukaj",
"violations_count": 7,
"screenshot": "/api/find-samples/550e8400-e29b-41d4-a716-446655440000/screenshot/search_form"
},
{
"sample_type": "data_table",
"url": "https://example.com/uslugi",
"violations_count": 2,
"screenshot": null
},
{
"sample_type": "interactive_elements",
"url": "https://example.com/o-nas",
"violations_count": 2,
"screenshot": null
}
]
},
"message": "Audyt zakończony pomyślnie. Znaleziono 12 typów naruszeń na 8 stronach."
}
Example response (404, Job not found):
{
"code": 404,
"status": "error",
"message": "Job not found"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get full a11y-fastscan report (completed jobs only)
Example request:
curl --request GET \
--get "https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/550e8400-e29b-41d4-a716-446655440000/report" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/550e8400-e29b-41d4-a716-446655440000/report"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/550e8400-e29b-41d4-a716-446655440000/report';
$response = $client->get(
$url,
[
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/a11y-fastscan/550e8400-e29b-41d4-a716-446655440000/report'
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Report available):
{
"summary": {
"total_pages_scanned": 8,
"pages_with_violations": 7,
"total_violations": 45,
"change_scale": "moderate"
},
"violations_by_type": [],
"pages_analyzed": []
}
Example response (404, Report not found):
{
"code": 404,
"status": "error",
"message": "Report not found - job may not be completed yet"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Jobs Management
Awaryjne zatrzymanie (kill) działającego joba asynchronicznego
Endpoint do killowania długo działających procesów collect-links i find-samples. Zabija proces PHP artisan przez PID i oznacza job jako failed z reason="killed".
Example request:
curl --request DELETE \
"https://crawler.deklaracja-dostepnosci.info//api/api/jobs/9d4e8c72-1234-5678-9abc-def012345678" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{
\"job_id\": \"0e690040-cdf8-3f95-96e3-0e7705a645d4\"
}"
const url = new URL(
"https://crawler.deklaracja-dostepnosci.info//api/api/jobs/9d4e8c72-1234-5678-9abc-def012345678"
);
const headers = {
"Accept": "application/json",
"Content-Type": "application/json",
};
let body = {
"job_id": "0e690040-cdf8-3f95-96e3-0e7705a645d4"
};
fetch(url, {
method: "DELETE",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://crawler.deklaracja-dostepnosci.info//api/api/jobs/9d4e8c72-1234-5678-9abc-def012345678';
$response = $client->delete(
$url,
[
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => [
'job_id' => '0e690040-cdf8-3f95-96e3-0e7705a645d4',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://crawler.deklaracja-dostepnosci.info//api/api/jobs/9d4e8c72-1234-5678-9abc-def012345678'
payload = {
"job_id": "0e690040-cdf8-3f95-96e3-0e7705a645d4"
}
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.request('DELETE', url, headers=headers, json=payload)
response.json()Example response (200, Job został zabity):
{
"code": 200,
"status": "failed",
"reason": "killed",
"message": "Job 9d4e8c72-1234-5678-9abc-def012345678 has been terminated",
"job_id": "9d4e8c72-1234-5678-9abc-def012345678"
}
Example response (404, Proces nie istnieje):
{
"code": 404,
"status": "error",
"message": "Process not found or already terminated",
"job_id": "9d4e8c72-1234-5678-9abc-def012345678"
}
Example response (404, Job nie znaleziony):
{
"code": 404,
"status": "error",
"message": "Job not found",
"job_id": "9d4e8c72-1234-5678-9abc-def012345678"
}
Example response (422, Błąd walidacji):
{
"message": "The given data was invalid.",
"errors": {
"job_id": [
"Job ID musi być w formacie UUID"
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.