Skip to content

Instantly share code, notes, and snippets.

@EncodeTheCode
Created February 19, 2026 13:14
Show Gist options
  • Select an option

  • Save EncodeTheCode/1c93c80617d0f487663da8e0a5eea64f to your computer and use it in GitHub Desktop.

Select an option

Save EncodeTheCode/1c93c80617d0f487663da8e0a5eea64f to your computer and use it in GitHub Desktop.
import requests
import dns.resolver
import whois
import tldextract
from tqdm import tqdm
from urllib.parse import urljoin, urlparse
# ----------------------------
# HTTP Redirect Resolver
# ----------------------------
def follow_redirects(url, max_redirects=20, timeout=10):
if not url.startswith(("http://", "https://")):
return None, "Invalid URL format"
session = requests.Session()
visited = set()
redirects = 0
progress = tqdm(total=max_redirects, desc="Resolving", unit="hop")
try:
response = session.get(url, allow_redirects=False, timeout=timeout)
while True:
if response.url in visited:
progress.close()
return None, "Redirect loop detected"
visited.add(response.url)
if not response.is_redirect:
if response.status_code >= 400:
progress.close()
return None, f"HTTP Error {response.status_code}"
progress.close()
return response.url, None
if redirects >= max_redirects:
progress.close()
return None, "Maximum redirects exceeded"
location = response.headers.get("Location")
if not location:
progress.close()
return None, "Redirect without Location header"
next_url = urljoin(response.url, location)
response = session.get(next_url, allow_redirects=False, timeout=timeout)
redirects += 1
progress.update(1)
except Exception as e:
progress.close()
return None, str(e)
finally:
session.close()
# ----------------------------
# Root Domain Extractor
# ----------------------------
def get_root_domain(domain):
extracted = tldextract.extract(domain)
if not extracted.domain or not extracted.suffix:
return None
return f"{extracted.domain}.{extracted.suffix}"
# ----------------------------
# DNS Information
# ----------------------------
def get_dns_info(domain):
info = {}
root_domain = get_root_domain(domain)
if not root_domain:
return {"DNS Error": "Unable to determine root domain"}
resolver = dns.resolver.Resolver()
resolver.timeout = 5
resolver.lifetime = 5
# A record
try:
info["A"] = [str(r) for r in resolver.resolve(root_domain, "A")]
except:
info["A"] = []
# AAAA record
try:
info["AAAA"] = [str(r) for r in resolver.resolve(root_domain, "AAAA")]
except:
info["AAAA"] = []
# NS record (authoritative level)
try:
info["NS"] = [str(r).rstrip('.') for r in resolver.resolve(root_domain, "NS")]
except Exception as e:
info["NS"] = []
info["NS_error"] = str(e)
# MX record
try:
info["MX"] = [str(r.exchange).rstrip('.') for r in resolver.resolve(root_domain, "MX")]
except:
info["MX"] = []
return info
# ----------------------------
# WHOIS Information
# ----------------------------
def get_whois_info(domain):
try:
w = whois.whois(domain)
return {
"Registrar": w.registrar,
"Creation Date": w.creation_date,
"Expiration Date": w.expiration_date,
"Name Servers (WHOIS)": w.name_servers,
"Organization": w.org,
"Country": w.country
}
except Exception as e:
return {"WHOIS Error": str(e)}
# ----------------------------
# Domain Extraction from URL
# ----------------------------
def extract_domain(url):
parsed = urlparse(url)
return parsed.netloc
# ----------------------------
# MAIN
# ----------------------------
if __name__ == "__main__":
user_input = input("Enter URL: ").strip()
if not user_input:
print("No input provided. Exiting.")
exit()
final_url, error = follow_redirects(user_input)
if error:
print("\nRedirect Resolution Error:", error)
exit()
print("\nFinal URL:", final_url)
domain = extract_domain(final_url)
print("Extracted Domain:", domain)
print("\n--- DNS Information ---")
dns_info = get_dns_info(domain)
for record_type, records in dns_info.items():
print(f"{record_type}: {records if records else 'None'}")
print("\n--- WHOIS Information ---")
whois_info = get_whois_info(get_root_domain(domain))
for key, value in whois_info.items():
print(f"{key}: {value}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment