Created
September 23, 2025 09:33
-
-
Save alordiel/0084717d683a5271f16da07b6ac8d102 to your computer and use it in GitHub Desktop.
Checks if links from current page (by selector) are redirecting or not. Use it from the browser's console (just copy->paste and run).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Link Redirect Checker for Browser Console | |
| // Note: CORS limitations apply - this will only work fully for same-origin links | |
| (async function checkLinkRedirects() { | |
| // Configuration | |
| const DOMAIN = 'https://www.example.com'; // This is used to match against location.origin | |
| const TIMEOUT = 5000; // Request timeout in milliseconds | |
| const SELECTOR = '#some-selector a[href]'; | |
| // Color codes for console output | |
| const colors = { | |
| redirect: 'color: orange; font-weight: bold', | |
| success: 'color: green', | |
| error: 'color: red', | |
| info: 'color: blue' | |
| }; | |
| // Get all anchor links from the page | |
| function getAllLinks() { | |
| const links = Array.from(document.querySelectorAll(SELECTOR)); | |
| const uniqueUrls = new Set(); | |
| links.forEach(link => { | |
| try { | |
| // Convert relative URLs to absolute | |
| const url = new URL(link.href, window.location.origin); | |
| // Filter by domain if specified | |
| if (!DOMAIN || url.origin === DOMAIN) { | |
| uniqueUrls.add(url.href); | |
| } | |
| } catch (e) { | |
| console.warn(`Invalid URL in href: ${link.href}`, e); | |
| } | |
| }); | |
| return Array.from(uniqueUrls); | |
| } | |
| // Check if a URL redirects (limited by CORS) | |
| async function checkRedirect(url) { | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), TIMEOUT); | |
| try { | |
| // For same-origin requests, we can use fetch with redirect: 'manual' | |
| const response = await fetch(url, { | |
| method: 'HEAD', // Use HEAD to avoid downloading body | |
| redirect: 'manual', // Don't follow redirects automatically | |
| signal: controller.signal, | |
| mode: 'no-cors' // This allows the request but limits response info | |
| }); | |
| clearTimeout(timeoutId); | |
| // Check if same-origin | |
| const urlObj = new URL(url); | |
| const isSameOrigin = urlObj.origin === window.location.origin; | |
| if (isSameOrigin) { | |
| // For same-origin, we get full response details | |
| if (response.type === 'opaqueredirect' || response.status === 301 || response.status === 302) { | |
| const location = response.headers.get('Location'); | |
| return { | |
| url: url, | |
| status: response.status || 'redirect', | |
| redirectTo: location || 'Unknown (CORS limited)', | |
| type: 'redirect' | |
| }; | |
| } else { | |
| return { | |
| url: url, | |
| status: response.status, | |
| type: 'normal' | |
| }; | |
| } | |
| } else { | |
| // For cross-origin, we have limited information | |
| return { | |
| url: url, | |
| status: 'CORS Limited', | |
| type: 'cors-limited', | |
| note: 'Cannot detect redirects due to CORS policy' | |
| }; | |
| } | |
| } catch (error) { | |
| clearTimeout(timeoutId); | |
| if (error.name === 'AbortError') { | |
| return { | |
| url: url, | |
| status: 'timeout', | |
| type: 'error', | |
| error: `Request timeout after ${TIMEOUT}ms` | |
| }; | |
| } | |
| return { | |
| url: url, | |
| status: 'error', | |
| type: 'error', | |
| error: error.message | |
| }; | |
| } | |
| } | |
| // Main execution | |
| console.log('Starting Link Redirect Checker...'); | |
| console.log(`Domain filter: ${DOMAIN || 'All domains'}`); | |
| console.log('-----------------------------------'); | |
| const links = getAllLinks(); | |
| console.log(`Found ${links.length} unique links to check`); | |
| console.log('-----------------------------------'); | |
| // Process links with rate limiting | |
| const results = { | |
| redirects: [], | |
| normal: [], | |
| errors: [], | |
| corsLimited: [] | |
| }; | |
| for (let i = 0; i < links.length; i++) { | |
| const url = links[i]; | |
| console.log(`Checking [${i + 1}/${links.length}]: ${url}`); | |
| const result = await checkRedirect(url); | |
| switch (result.type) { | |
| case 'redirect': | |
| console.log(`%c ↳ REDIRECT (${result.status}): → ${result.redirectTo}`, colors.redirect); | |
| results.redirects.push(result); | |
| break; | |
| case 'error': | |
| case 'timeout': | |
| console.log(`%c ✗ ERROR: ${result.error || result.status}`, colors.error); | |
| results.errors.push(result); | |
| break; | |
| case 'cors-limited': | |
| console.log(`%c ⚠ CORS LIMITED: Cannot check cross-origin`, colors.info); | |
| results.corsLimited.push(result); | |
| break; | |
| } | |
| // Small delay to avoid overwhelming the browser | |
| await new Promise(resolve => setTimeout(resolve, 100)); | |
| } | |
| // Summary | |
| console.log('\n%c===================================', colors.info); | |
| console.log('%c📊 SUMMARY', colors.info); | |
| console.log('%c===================================', colors.info); | |
| console.log(`Total links checked: ${links.length}`); | |
| console.log(`%c✓ Normal (200 OK): ${results.normal.length}`, colors.success); | |
| console.log(`%c↻ Redirects found: ${results.redirects.length}`, colors.redirect); | |
| console.log(`%c✗ Errors: ${results.errors.length}`, colors.error); | |
| console.log(`%c⚠ CORS Limited: ${results.corsLimited.length}`, colors.info); | |
| if (results.redirects.length > 0) { | |
| console.log('\n%c📋 REDIRECT DETAILS:', colors.redirect); | |
| console.table(results.redirects.map(r => ({ | |
| URL: r.url, | |
| Status: r.status, | |
| 'Redirects To': r.redirectTo | |
| }))); | |
| } | |
| if (results.errors.length > 0) { | |
| console.log('\n%c❌ ERROR DETAILS:', colors.error); | |
| console.table(results.errors.map(r => ({ | |
| URL: r.url, | |
| Error: r.error || r.status | |
| }))); | |
| } | |
| // Return results for further processing if needed | |
| return results; | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment