Created
August 19, 2025 09:11
-
-
Save meysam81/bc464849e5d75847bd85021903f30242 to your computer and use it in GitHub Desktop.
Check for availability of a given product name and its possible TLD domains using DNS check and WHOIS API call; use at your own discretion!
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
| #!/bin/bash | |
| # Unified Domain Generator & Availability Checker | |
| # Can accept either raw names to generate domains or a list of domains to check | |
| # Usage: ./domain_tool.sh --names names.txt [options] | |
| # ./domain_tool.sh --domains domains.txt [options] | |
| # Color codes | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| BLUE='\033[0;34m' | |
| YELLOW='\033[1;33m' | |
| CYAN='\033[0;36m' | |
| NC='\033[0m' | |
| # Default B2B SaaS-friendly TLDs | |
| DEFAULT_TLDS=( | |
| "com" # Universal, most trusted | |
| "io" # Tech startups | |
| "app" # Applications | |
| "so" # Trendy for SaaS | |
| "dev" # Developer tools | |
| "ai" # AI/ML companies | |
| "co" # Company/startup alternative | |
| "tech" # Technology companies | |
| "cloud" # Cloud services | |
| "tools" # SaaS tools | |
| "software" # Software companies | |
| "solutions" # B2B solutions | |
| "platform" # Platform businesses | |
| "systems" # Enterprise systems | |
| "pro" # Professional services | |
| ) | |
| # Function to display usage | |
| show_usage() { | |
| echo "Unified Domain Generator & Availability Checker" | |
| echo "" | |
| echo "Usage:" | |
| echo " $0 --names <file> [options] # Generate domains from names, then check" | |
| echo " $0 --domains <file> [options] # Check existing domain list" | |
| echo "" | |
| echo "Input Options:" | |
| echo " --names FILE Input file with base names (one per line)" | |
| echo " --domains FILE Input file with full domains (one per line)" | |
| echo "" | |
| echo "Generation Options (for --names mode):" | |
| echo " -t, --tlds LIST Comma-separated list of TLDs (overrides defaults)" | |
| echo " -a, --add-tlds LIST Add TLDs to default list" | |
| echo " -m, --minimal Use minimal TLD set (com,io,app,so,dev,ai)" | |
| echo " -p, --prefixes LIST Add prefixes to names (e.g., 'get,try,use')" | |
| echo " -s, --suffixes LIST Add suffixes to names (e.g., 'app,hub,hq')" | |
| echo "" | |
| echo "Checking Options:" | |
| echo " --skip-dns Skip DNS checks (faster but less accurate)" | |
| echo " --skip-whois Skip WHOIS checks (avoids rate limiting)" | |
| echo " --delay SECONDS Delay between checks (default: 0.5)" | |
| echo " --available-only Only show available domains in output" | |
| echo "" | |
| echo "Output Options:" | |
| echo " -o, --output FILE Base name for output files (default: domain_results)" | |
| echo " --keep-temp Keep temporary generated domains file" | |
| echo "" | |
| echo "General Options:" | |
| echo " -h, --help Show this help message" | |
| echo "" | |
| echo "Examples:" | |
| echo " # Generate and check domains from names" | |
| echo " $0 --names startup_names.txt -m --available-only" | |
| echo "" | |
| echo " # Check existing domain list" | |
| echo " $0 --domains my_domains.txt --skip-whois" | |
| echo "" | |
| echo " # Generate with prefixes/suffixes and check" | |
| echo " $0 --names names.txt -p 'get,try' -s 'app,hub' -t 'com,io'" | |
| } | |
| # Initialize variables | |
| INPUT_MODE="" | |
| INPUT_FILE="" | |
| OUTPUT_BASE="domain_results" | |
| CUSTOM_TLDS="" | |
| ADD_TLDS="" | |
| USE_MINIMAL=false | |
| PREFIXES="" | |
| SUFFIXES="" | |
| SKIP_DNS=false | |
| SKIP_WHOIS=false | |
| CHECK_DELAY=0.5 | |
| AVAILABLE_ONLY=false | |
| KEEP_TEMP=false | |
| TEMP_DOMAINS_FILE="" | |
| # Parse command line arguments | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| --names) | |
| INPUT_MODE="names" | |
| INPUT_FILE="$2" | |
| shift 2 | |
| ;; | |
| --domains) | |
| INPUT_MODE="domains" | |
| INPUT_FILE="$2" | |
| shift 2 | |
| ;; | |
| -t|--tlds) | |
| CUSTOM_TLDS="$2" | |
| shift 2 | |
| ;; | |
| -a|--add-tlds) | |
| ADD_TLDS="$2" | |
| shift 2 | |
| ;; | |
| -m|--minimal) | |
| USE_MINIMAL=true | |
| shift | |
| ;; | |
| -p|--prefixes) | |
| PREFIXES="$2" | |
| shift 2 | |
| ;; | |
| -s|--suffixes) | |
| SUFFIXES="$2" | |
| shift 2 | |
| ;; | |
| --skip-dns) | |
| SKIP_DNS=true | |
| shift | |
| ;; | |
| --skip-whois) | |
| SKIP_WHOIS=true | |
| shift | |
| ;; | |
| --delay) | |
| CHECK_DELAY="$2" | |
| shift 2 | |
| ;; | |
| --available-only) | |
| AVAILABLE_ONLY=true | |
| shift | |
| ;; | |
| -o|--output) | |
| OUTPUT_BASE="$2" | |
| shift 2 | |
| ;; | |
| --keep-temp) | |
| KEEP_TEMP=true | |
| shift | |
| ;; | |
| -h|--help) | |
| show_usage | |
| exit 0 | |
| ;; | |
| *) | |
| echo "Unknown option: $1" | |
| show_usage | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| # Validate input | |
| if [ -z "$INPUT_MODE" ] || [ -z "$INPUT_FILE" ]; then | |
| echo -e "${RED}Error: You must specify either --names or --domains with a file${NC}" | |
| echo "" | |
| show_usage | |
| exit 1 | |
| fi | |
| if [ ! -f "$INPUT_FILE" ]; then | |
| echo -e "${RED}Error: File $INPUT_FILE not found${NC}" | |
| exit 1 | |
| fi | |
| # Function to generate domains from names | |
| generate_domains() { | |
| local names_file="$1" | |
| local output_file="$2" | |
| # Determine which TLDs to use | |
| local tlds=() | |
| if [ "$USE_MINIMAL" = true ]; then | |
| tlds=("com" "io" "app" "so" "dev" "ai") | |
| elif [ -n "$CUSTOM_TLDS" ]; then | |
| IFS=',' read -ra tlds <<< "$CUSTOM_TLDS" | |
| else | |
| tlds=("${DEFAULT_TLDS[@]}") | |
| fi | |
| # Add additional TLDs if specified | |
| if [ -n "$ADD_TLDS" ]; then | |
| IFS=',' read -ra ADDITIONAL <<< "$ADD_TLDS" | |
| tlds+=("${ADDITIONAL[@]}") | |
| fi | |
| # Parse prefixes and suffixes | |
| IFS=',' read -ra PREFIX_ARRAY <<< "$PREFIXES" | |
| IFS=',' read -ra SUFFIX_ARRAY <<< "$SUFFIXES" | |
| # Clear output file | |
| > "$output_file" | |
| echo -e "${BLUE}Generating domains...${NC}" | |
| echo -n "TLDs: " | |
| echo "${tlds[@]}" | tr ' ' ',' | |
| [ -n "$PREFIXES" ] && echo "Prefixes: $PREFIXES" | |
| [ -n "$SUFFIXES" ] && echo "Suffixes: $SUFFIXES" | |
| local total_names=0 | |
| local total_domains=0 | |
| # Process each name | |
| while IFS= read -r name || [ -n "$name" ]; do | |
| # Clean the name | |
| name=$(echo "$name" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]') | |
| [ -z "$name" ] && continue | |
| ((total_names++)) | |
| # Generate variations | |
| local variations=() | |
| variations+=("$name") | |
| for prefix in "${PREFIX_ARRAY[@]}"; do | |
| [ -n "$prefix" ] && variations+=("${prefix}${name}") | |
| done | |
| for suffix in "${SUFFIX_ARRAY[@]}"; do | |
| [ -n "$suffix" ] && variations+=("${name}${suffix}") | |
| done | |
| for prefix in "${PREFIX_ARRAY[@]}"; do | |
| for suffix in "${SUFFIX_ARRAY[@]}"; do | |
| [ -n "$prefix" ] && [ -n "$suffix" ] && variations+=("${prefix}${name}${suffix}") | |
| done | |
| done | |
| # Generate domains with all TLDs | |
| for variant in "${variations[@]}"; do | |
| for tld in "${tlds[@]}"; do | |
| echo "${variant}.${tld}" >> "$output_file" | |
| ((total_domains++)) | |
| done | |
| done | |
| done < "$names_file" | |
| # Sort and remove duplicates | |
| sort -u "$output_file" -o "$output_file" | |
| local unique_domains=$(wc -l < "$output_file") | |
| echo -e "${GREEN}Generated $unique_domains unique domains from $total_names names${NC}" | |
| } | |
| # Function to check domain using DNS | |
| check_dns() { | |
| local domain=$1 | |
| if [ "$SKIP_DNS" = true ]; then | |
| echo "Skipped" | |
| return 2 | |
| fi | |
| if dig +short NS "$domain" 2>/dev/null | grep -q .; then | |
| echo "Has_DNS" | |
| return 1 # Domain has NS records (likely taken) | |
| else | |
| echo "No_DNS" | |
| return 0 # No NS records (possibly available) | |
| fi | |
| } | |
| # Function to check domain using WHOIS | |
| check_whois() { | |
| local domain=$1 | |
| if [ "$SKIP_WHOIS" = true ]; then | |
| echo "Skipped" | |
| return 2 | |
| fi | |
| local whois_output | |
| whois_output=$(timeout 5 whois "$domain" 2>/dev/null) | |
| if echo "$whois_output" | grep -qiE "No match|Not found|No Data Found|No entries found|Status: free|available"; then | |
| echo "Not_Found" | |
| return 0 # Likely available | |
| elif echo "$whois_output" | grep -qiE "Domain Name:|Registrar:|Creation Date:|Status: ACTIVE|Status: ok"; then | |
| echo "Registered" | |
| return 1 # Definitely taken | |
| else | |
| echo "Uncertain" | |
| return 2 # Uncertain | |
| fi | |
| } | |
| # Function to check domains | |
| check_domains() { | |
| local domains_file="$1" | |
| local results_file="${OUTPUT_BASE}_$(date +%Y%m%d_%H%M%S).csv" | |
| echo -e "${BLUE}Starting domain availability check...${NC}" | |
| echo "Results will be saved to: $results_file" | |
| echo "" | |
| # Initialize results file | |
| echo "Domain,DNS_Status,WHOIS_Status,Likely_Available" > "$results_file" | |
| local total_domains=$(wc -l < "$domains_file") | |
| local current=0 | |
| local available_domains=() | |
| while IFS= read -r domain || [ -n "$domain" ]; do | |
| domain=$(echo "$domain" | tr -d '[:space:]') | |
| [ -z "$domain" ] && continue | |
| ((current++)) | |
| echo -n "[$current/$total_domains] Checking $domain... " | |
| # Check DNS | |
| dns_status=$(check_dns "$domain") | |
| dns_result=$? | |
| # Add delay before WHOIS check | |
| sleep "$CHECK_DELAY" | |
| # Check WHOIS | |
| whois_status=$(check_whois "$domain") | |
| whois_result=$? | |
| # Determine likely availability | |
| if { [ $dns_result -eq 0 ] || [ $dns_result -eq 2 ]; } && | |
| { [ $whois_result -eq 0 ] || [ $whois_result -eq 2 ]; } && | |
| { [ $dns_result -eq 0 ] || [ $whois_result -eq 0 ]; }; then | |
| likely_available="YES" | |
| available_domains+=("$domain") | |
| echo -e "${GREEN}LIKELY AVAILABLE${NC}" | |
| elif [ $dns_result -eq 1 ] || [ $whois_result -eq 1 ]; then | |
| likely_available="NO" | |
| echo -e "${RED}TAKEN${NC}" | |
| else | |
| likely_available="UNCERTAIN" | |
| echo -e "${YELLOW}UNCERTAIN${NC}" | |
| fi | |
| # Save to CSV (unless available-only mode and domain is not available) | |
| if [ "$AVAILABLE_ONLY" = false ] || [ "$likely_available" = "YES" ]; then | |
| echo "$domain,$dns_status,$whois_status,$likely_available" >> "$results_file" | |
| fi | |
| done < "$domains_file" | |
| # Summary | |
| echo "" | |
| echo -e "${CYAN}═══════════════════════════════════${NC}" | |
| echo -e "${CYAN} CHECKING COMPLETE${NC}" | |
| echo -e "${CYAN}═══════════════════════════════════${NC}" | |
| local available_count=${#available_domains[@]} | |
| local taken_count=$(grep -c ",NO$" "$results_file" 2>/dev/null || echo 0) | |
| local uncertain_count=$(grep -c ",UNCERTAIN$" "$results_file" 2>/dev/null || echo 0) | |
| echo "Summary:" | |
| echo " Total checked: $current" | |
| echo -e " ${GREEN}Likely available: $available_count${NC}" | |
| echo -e " ${RED}Taken: $taken_count${NC}" | |
| echo -e " ${YELLOW}Uncertain: $uncertain_count${NC}" | |
| # Display available domains | |
| if [ $available_count -gt 0 ]; then | |
| echo "" | |
| echo -e "${GREEN}Available domains:${NC}" | |
| for domain in "${available_domains[@]}"; do | |
| echo " ✓ $domain" | |
| done | |
| # Save available domains to separate file | |
| available_file="${OUTPUT_BASE}_available.txt" | |
| printf "%s\n" "${available_domains[@]}" > "$available_file" | |
| echo "" | |
| echo -e "${GREEN}Available domains saved to: $available_file${NC}" | |
| fi | |
| echo "" | |
| echo "Full results saved to: $results_file" | |
| } | |
| # Main execution | |
| echo -e "${CYAN}═══════════════════════════════════════════${NC}" | |
| echo -e "${CYAN} Domain Generator & Availability Checker${NC}" | |
| echo -e "${CYAN}═══════════════════════════════════════════${NC}" | |
| echo "" | |
| # Process based on input mode | |
| if [ "$INPUT_MODE" = "names" ]; then | |
| # Generate domains first | |
| TEMP_DOMAINS_FILE="${OUTPUT_BASE}_generated_$(date +%Y%m%d_%H%M%S).txt" | |
| generate_domains "$INPUT_FILE" "$TEMP_DOMAINS_FILE" | |
| echo "" | |
| # Show sample of generated domains | |
| echo "Sample generated domains (first 5):" | |
| head -5 "$TEMP_DOMAINS_FILE" | while read -r domain; do | |
| echo " • $domain" | |
| done | |
| total_generated=$(wc -l < "$TEMP_DOMAINS_FILE") | |
| [ $total_generated -gt 5 ] && echo " ... and $((total_generated - 5)) more" | |
| echo "" | |
| # Check the generated domains | |
| check_domains "$TEMP_DOMAINS_FILE" | |
| # Clean up temp file unless requested to keep | |
| if [ "$KEEP_TEMP" = false ]; then | |
| rm -f "$TEMP_DOMAINS_FILE" | |
| else | |
| echo "Generated domains file kept at: $TEMP_DOMAINS_FILE" | |
| fi | |
| else | |
| # Direct domain checking | |
| check_domains "$INPUT_FILE" | |
| fi | |
| echo "" | |
| echo -e "${CYAN}All operations complete!${NC}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment