Website Alive Check
Verifies a website is serving correctly by checking HTTP status, content presence, layout integrity, visual rendering, and resource loading.
Quick Start
# First time setup (installs dependencies)
bash scripts/setup.sh
# Run health check
python3 scripts/check_alive.py https://example.com
# With options
python3 scripts/check_alive.py https://example.com --screenshot=/tmp/site.png --json
Setup (One-Time)
Run the setup script to install dependencies:
bash scripts/setup.sh
This will:
- Verify Python 3 is installed
- Verify pip is available
- Install Playwright (
pip3 install playwright) - Install Chromium browser (
python3 -m playwright install chromium)
Manual Setup
If you prefer manual installation:
# Install Playwright
pip3 install playwright
# Install Chromium browser
python3 -m playwright install chromium
Usage
Command Line
# Basic check
python3 scripts/check_alive.py <url>
# With custom threshold (default: 0.7 = 70%)
python3 scripts/check_alive.py <url> --threshold=0.8
# Save screenshot
python3 scripts/check_alive.py <url> --screenshot=/tmp/screenshot.png
# JSON output (for automation)
python3 scripts/check_alive.py <url> --json
# Combined
python3 scripts/check_alive.py https://example.com --threshold=0.8 --screenshot=/tmp/site.png --json
Exit Codes
0- Site is alive (score >= threshold)1- Site is not alive (score < threshold or error)
Input
| Parameter | Required | Default | Description |
|---|---|---|---|
url | Yes | - | The website URL to check |
--threshold | No | 0.7 | Minimum health score to pass (0.0-1.0) |
--screenshot | No | - | Path to save screenshot |
--json | No | false | Output results as JSON |
Health Check Categories
1. HTTP Response
- Returns 2xx status code
- Response time is recorded
2. Content Presence (20% weight)
- Page has meaningful text content (> 100 characters) - 15%
- Primary heading (h1) exists - 5%
3. Error Detection (15% weight)
- No error keywords visible ("404", "500", "error", "not found", "maintenance", "unavailable")
4. Layout Integrity (25% weight)
- Body has reasonable dimensions (width > 300px, height > 200px) - 10%
- Main content area exists and is not collapsed - 10%
- No major horizontal overflow - 5%
5. Visual Rendering (20% weight)
- CSS stylesheets applied (not unstyled HTML) - 10%
- Critical images loaded (no broken images) - 10%
6. Interactive Readiness (15% weight)
- No blocking JavaScript errors - 5%
- No stuck loading spinners - 5%
- No full-screen blocking overlays/modals - 5%
7. Resource Loading (5% weight)
- No critical resource failures (CSS, fonts, scripts)
Scoring
| Check | Weight |
|---|---|
| HTTP 2xx | Required (fail = 0 score) |
| Has content (>100 chars) | 15% |
| Has H1 | 5% |
| No error text | 15% |
| Reasonable size | 10% |
| Main content exists | 10% |
| No overflow | 5% |
| Styles applied | 10% |
| Images loaded | 10% |
| No console errors | 5% |
| No stuck loader | 5% |
| No blocking overlay | 5% |
| No critical resource failures | 5% |
Site is "alive" if:
- HTTP returns 2xx AND
- Health score >= threshold (default 70%)
Output Format
Human-Readable (default)
============================================================
WEBSITE ALIVE CHECK: PASSED
============================================================
URL: https://example.com
Score: 95%
HTTP Status: 200
Response Time: 1234ms
Screenshot: /tmp/site.png
CHECKS:
[+] hasContent
[+] hasH1
[+] noErrorText
[+] hasReasonableSize
[+] hasMainContent
[-] noOverflow
[+] hasStyles
[+] imagesLoaded
[+] noConsoleErrors
[+] noStuckLoader
[+] noBlockingOverlay
[+] noCriticalResourceFailures
DETAILS:
textLength: 5420
bodyDimensions: 1280x5784
scrollHeight: 5784
totalImages: 159
brokenImages: 0
fontFamily: Lexend, Roboto, Helvetica, Arial, sans-seri
JSON (--json flag)
{
"url": "https://example.com",
"timestamp": "2024-01-15T10:30:00Z",
"alive": true,
"score": 0.95,
"screenshot": "/tmp/site.png",
"http": {
"status": 200,
"ok": true,
"responseTime": 1234
},
"checks": {
"hasContent": true,
"hasH1": true,
"noErrorText": true,
"hasReasonableSize": true,
"hasMainContent": true,
"noOverflow": false,
"hasStyles": true,
"imagesLoaded": true,
"noConsoleErrors": true,
"noStuckLoader": true,
"noBlockingOverlay": true,
"noCriticalResourceFailures": true
},
"details": {
"textLength": 5420,
"bodyDimensions": "1280x5784",
"scrollHeight": 5784,
"totalImages": 159,
"brokenImages": 0,
"fontFamily": "Lexend, Roboto, Helvetica, Arial, sans-seri",
"consoleErrors": [],
"failedResources": []
}
}
Examples
Basic Health Check
python3 scripts/check_alive.py https://www.google.com
Post-Deployment Verification
# Check with strict threshold and save evidence
python3 scripts/check_alive.py https://myapp.com --threshold=0.9 --screenshot=/tmp/deploy-check.png
# Use exit code in CI/CD
if python3 scripts/check_alive.py https://myapp.com --threshold=0.8; then
echo "Deployment successful!"
else
echo "Site health check failed!"
exit 1
fi
Batch Check Multiple Sites
for site in "https://site1.com" "https://site2.com" "https://site3.com"; do
echo "Checking: $site"
python3 scripts/check_alive.py "$site" --json >> results.json
done
Monitoring Integration
# Output JSON for parsing by monitoring tools
python3 scripts/check_alive.py https://mysite.com --json | jq '.alive'
Notes
- The script waits for
networkidle+ 2 seconds for lazy-loaded content - Screenshots capture the viewport (1280x800), not full page
- Some sites may trigger false positives for "stuck loader" if they have permanent loading indicators
- Cookie banners/GDPR modals may trigger "blocking overlay" - these are expected
- Analytics/tracking request failures (Google Analytics, etc.) are ignored - only CSS, fonts, and scripts count as critical
- For SPAs, the script waits for client-side rendering to complete
Troubleshooting
"Playwright is not installed"
pip3 install playwright
python3 -m playwright install chromium
"Browser not found"
python3 -m playwright install chromium
Timeout errors
The default timeout is 30 seconds. For slow sites, you may need to modify the script or check network connectivity.
Permission denied on screenshot
Ensure the screenshot path is writable:
python3 scripts/check_alive.py https://example.com --screenshot=/tmp/site.png