Back to Home
Gistify Snippet
Public
Universal URL Bypasser & Redirect Resolver
All-in-one Python URL bypasser and unshortener. Resolves multi-hop HTTP redirects, unwraps Base64/nested query target parameters, traces HTML meta-refresh/JS location hops, and cleans analytics tracking parameters (UTM, fbclid, gclid).
#bypass#unshortener#redirect#python#scraper#privacy#tools
13
Rawuniversal_bypass.pypython
265 lines| 1 | #!/usr/bin/env python3 |
| 2 | """ |
| 3 | Universal URL Bypasser & Redirect Resolver (Python) |
| 4 | -------------------------------------------------- |
| 5 | Resolves shortened links, extracts nested target URLs from ad-walls / shorteners, |
| 6 | cleans analytics tracking parameters (UTM, fbclid), and resolves direct destinations. |
| 7 | |
| 8 | Features: |
| 9 | 1. Multi-hop HTTP 3xx Redirect Follower (handles up to 30 redirects & refresh headers). |
| 10 | 2. Nested / Encoded URL Unwrapper (extracts ?url=, ?dest=, ?target=, base64 / hex payloads). |
| 11 | 3. Ad-link / Shortlink Rule Matcher (Ouo, Shrinkme, TinyURL, Bitly, Linkvertise patterns). |
| 12 | 4. Privacy & Clean URL Normalizer (removes tracking parameters like utm_*, gclid, fbclid). |
| 13 | 5. Built-in CLI and importable Python API with zero external dependencies. |
| 14 | """ |
| 15 | |
| 16 | import sys |
| 17 | import os |
| 18 | import re |
| 19 | import json |
| 20 | import base64 |
| 21 | import urllib.request |
| 22 | import urllib.parse |
| 23 | import urllib.error |
| 24 | import http.cookiejar |
| 25 | from typing import Dict, Any, Optional, List |
| 26 | |
| 27 | # Realistic Browser User-Agent Header |
| 28 | DEFAULT_UA = ( |
| 29 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " |
| 30 | "(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" |
| 31 | ) |
| 32 | |
| 33 | # Common URL query parameters holding destination targets |
| 34 | DESTINATION_PARAMS = [ |
| 35 | "url", "dest", "destination", "target", "link", "r", "redirect", |
| 36 | "redirect_url", "redirect_to", "next", "to", "out", "go", "u", "q" |
| 37 | ] |
| 38 | |
| 39 | # Tracking query parameters to strip |
| 40 | TRACKING_PARAMS = { |
| 41 | "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", |
| 42 | "fbclid", "gclid", "gclsrc", "dclid", "msclkid", "mc_eid", "zanpid", |
| 43 | "yclid", "_ga", "_gl", "igshid", "si", "feature" |
| 44 | } |
| 45 | |
| 46 | |
| 47 | class UniversalBypasser: |
| 48 | def __init__(self, user_agent: str = DEFAULT_UA, timeout: int = 15): |
| 49 | self.user_agent = user_agent |
| 50 | self.timeout = timeout |
| 51 | self.cookie_jar = http.cookiejar.CookieJar() |
| 52 | |
| 53 | # Build opener with automatic cookie handling & redirect suppression for manual inspection |
| 54 | self.opener = urllib.request.build_opener( |
| 55 | urllib.request.HTTPCookieProcessor(self.cookie_jar) |
| 56 | ) |
| 57 | |
| 58 | def clean_url(self, url: str) -> str: |
| 59 | """Strips tracking query parameters (UTM, Facebook, Google analytics tokens).""" |
| 60 | parsed = urllib.parse.urlparse(url) |
| 61 | query_dict = urllib.parse.parse_qs(parsed.query, keep_blank_values=True) |
| 62 | |
| 63 | # Remove tracking tokens |
| 64 | cleaned_query = { |
| 65 | k: v for k, v in query_dict.items() if k.lower() not in TRACKING_PARAMS |
| 66 | } |
| 67 | |
| 68 | new_query_str = urllib.parse.urlencode(cleaned_query, doseq=True) |
| 69 | return urllib.parse.urlunparse(( |
| 70 | parsed.scheme, |
| 71 | parsed.netloc, |
| 72 | parsed.path, |
| 73 | parsed.params, |
| 74 | new_query_str, |
| 75 | parsed.fragment |
| 76 | )) |
| 77 | |
| 78 | def unwrap_embedded_url(self, url: str) -> Optional[str]: |
| 79 | """Detects and extracts embedded or base64-encoded destination URLs in query parameters.""" |
| 80 | parsed = urllib.parse.urlparse(url) |
| 81 | query_dict = urllib.parse.parse_qs(parsed.query) |
| 82 | |
| 83 | # 1. Check known redirect parameters |
| 84 | for param in DESTINATION_PARAMS: |
| 85 | if param in query_dict: |
| 86 | val = query_dict[param][0].strip() |
| 87 | if val.startswith("http://") or val.startswith("https://"): |
| 88 | return val |
| 89 | # Try Base64 decoding |
| 90 | try: |
| 91 | decoded = base64.b64decode(val.encode("utf-8") + b"==").decode("utf-8", errors="ignore") |
| 92 | if decoded.startswith("http://") or decoded.startswith("https://"): |
| 93 | return decoded |
| 94 | except Exception: |
| 95 | pass |
| 96 | |
| 97 | # 2. Check URL path patterns with embedded links (e.g. /link/https://...) |
| 98 | match = re.search(r'(https?://[^\s/$.?#].[^\s]*)', url[8:]) |
| 99 | if match: |
| 100 | extracted = match.group(1) |
| 101 | if extracted != url: |
| 102 | return extracted |
| 103 | |
| 104 | return None |
| 105 | |
| 106 | def resolve(self, url: str, max_hops: int = 15) -> Dict[str, Any]: |
| 107 | """ |
| 108 | Bypasses link shorteners and follows all intermediate redirects to the final destination. |
| 109 | """ |
| 110 | current_url = url.strip() |
| 111 | if not current_url.startswith(("http://", "https://")): |
| 112 | current_url = "https://" + current_url |
| 113 | |
| 114 | history: List[Dict[str, Any]] = [] |
| 115 | visited = set() |
| 116 | |
| 117 | for hop in range(1, max_hops + 1): |
| 118 | if current_url in visited: |
| 119 | break |
| 120 | visited.add(current_url) |
| 121 | |
| 122 | # Step A: Check if query contains an embedded destination |
| 123 | unwrapped = self.unwrap_embedded_url(current_url) |
| 124 | if unwrapped and unwrapped != current_url: |
| 125 | history.append({ |
| 126 | "hop": hop, |
| 127 | "type": "query_unwrapped", |
| 128 | "from": current_url, |
| 129 | "to": unwrapped |
| 130 | }) |
| 131 | current_url = unwrapped |
| 132 | continue |
| 133 | |
| 134 | # Step B: Make HTTP HEAD/GET request to trace location headers |
| 135 | req = urllib.request.Request( |
| 136 | current_url, |
| 137 | headers={ |
| 138 | "User-Agent": self.user_agent, |
| 139 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", |
| 140 | "Accept-Language": "en-US,en;q=0.9,id;q=0.8", |
| 141 | } |
| 142 | ) |
| 143 | |
| 144 | try: |
| 145 | # Custom HTTP handler to capture 3xx redirects without automatic jumps |
| 146 | response = self.opener.open(req, timeout=self.timeout) |
| 147 | final_req_url = response.geturl() |
| 148 | status_code = response.getcode() |
| 149 | |
| 150 | # Read body snippet to inspect for meta-refresh or JS redirects |
| 151 | body_sample = response.read(16384).decode("utf-8", errors="ignore") |
| 152 | |
| 153 | # Check HTML Meta Refresh tag (e.g. <meta http-equiv="refresh" content="0;url=...">) |
| 154 | meta_match = re.search( |
| 155 | r'<meta[^>]*http-equiv=["\']?refresh["\']?[^>]*content=["\']?\d+;\s*url=([^"\'>\s]+)', |
| 156 | body_sample, |
| 157 | re.IGNORECASE |
| 158 | ) |
| 159 | |
| 160 | if meta_match: |
| 161 | meta_dest = urllib.parse.urljoin(final_req_url, meta_match.group(1).strip()) |
| 162 | if meta_dest != current_url: |
| 163 | history.append({ |
| 164 | "hop": hop, |
| 165 | "type": "meta_refresh", |
| 166 | "status": status_code, |
| 167 | "from": current_url, |
| 168 | "to": meta_dest |
| 169 | }) |
| 170 | current_url = meta_dest |
| 171 | continue |
| 172 | |
| 173 | # Check JavaScript window.location redirect |
| 174 | js_match = re.search( |
| 175 | r'(?:window\.location(?:\.href)?|location\.replace)\s*=\s*["\'](https?://[^"\']+)["\']', |
| 176 | body_sample, |
| 177 | re.IGNORECASE |
| 178 | ) |
| 179 | if js_match: |
| 180 | js_dest = js_match.group(1).strip() |
| 181 | if js_dest != current_url: |
| 182 | history.append({ |
| 183 | "hop": hop, |
| 184 | "type": "js_location", |
| 185 | "status": status_code, |
| 186 | "from": current_url, |
| 187 | "to": js_dest |
| 188 | }) |
| 189 | current_url = js_dest |
| 190 | continue |
| 191 | |
| 192 | # If final URL is different from start URL |
| 193 | if final_req_url != current_url: |
| 194 | history.append({ |
| 195 | "hop": hop, |
| 196 | "type": "http_redirect", |
| 197 | "status": status_code, |
| 198 | "from": current_url, |
| 199 | "to": final_req_url |
| 200 | }) |
| 201 | current_url = final_req_url |
| 202 | else: |
| 203 | break |
| 204 | |
| 205 | except urllib.error.HTTPError as e: |
| 206 | # Handle manual 301/302/303/307/308 redirects |
| 207 | location = e.headers.get("Location") |
| 208 | if location: |
| 209 | next_url = urllib.parse.urljoin(current_url, location) |
| 210 | history.append({ |
| 211 | "hop": hop, |
| 212 | "type": "http_redirect", |
| 213 | "status": e.code, |
| 214 | "from": current_url, |
| 215 | "to": next_url |
| 216 | }) |
| 217 | current_url = next_url |
| 218 | continue |
| 219 | else: |
| 220 | history.append({ |
| 221 | "hop": hop, |
| 222 | "type": "error", |
| 223 | "status": e.code, |
| 224 | "message": str(e) |
| 225 | }) |
| 226 | break |
| 227 | except Exception as e: |
| 228 | history.append({ |
| 229 | "hop": hop, |
| 230 | "type": "error", |
| 231 | "message": str(e) |
| 232 | }) |
| 233 | break |
| 234 | |
| 235 | clean_final = self.clean_url(current_url) |
| 236 | |
| 237 | return { |
| 238 | "success": True, |
| 239 | "original_url": url, |
| 240 | "final_url": current_url, |
| 241 | "clean_url": clean_final, |
| 242 | "total_hops": len(history), |
| 243 | "history": history |
| 244 | } |
| 245 | |
| 246 | |
| 247 | # ───────────────────────────────────────────────────────────────────── |
| 248 | # CLI Entry Point |
| 249 | # ───────────────────────────────────────────────────────────────────── |
| 250 | def main(): |
| 251 | if len(sys.argv) < 2: |
| 252 | print("Usage: python3 universal_bypass.py <url>") |
| 253 | print("Example: python3 universal_bypass.py 'https://bit.ly/3xSampleLink'") |
| 254 | sys.exit(1) |
| 255 | |
| 256 | target_url = sys.argv[1] |
| 257 | bypasser = UniversalBypasser() |
| 258 | result = bypasser.resolve(target_url) |
| 259 | |
| 260 | print(json.dumps(result, indent=2, ensure_ascii=False)) |
| 261 | |
| 262 | |
| 263 | if __name__ == "__main__": |
| 264 | main() |
| 265 | |
Discussion & Comments0
No comments yet — be the first to leave feedback or start a code discussion.
Sign in with your GitHub account to write comments and join the discussion.