Skip to main content
Glama
cnych

Backlinks MCP

by cnych

get_backlinks_list

Retrieve a list of backlinks for any domain to analyze SEO performance, including title, URL, and domain rating data.

Instructions

Get backlinks list for the specified domain
Args:
    domain (str): The domain to query
Returns:
    List of backlinks for the domain, containing title, URL, domain rating, etc.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
domainYes

Implementation Reference

  • The primary handler function for the 'get_backlinks_list' tool. Decorated with @mcp.tool() for registration. Orchestrates caching, token acquisition, signature retrieval, and backlinks fetching.
    @mcp.tool()
    def get_backlinks_list(domain: str) -> Optional[Dict[str, Any]]:
        """
        Get backlinks list for the specified domain
        Args:
            domain (str): The domain to query
        Returns:
            List of backlinks for the domain, containing title, URL, domain rating, etc.
        """
        # Try to get signature from cache
        signature, valid_until, overview_data = load_signature_from_cache(domain)
        
        # If no valid signature in cache, get a new one
        if not signature or not valid_until:
            # Step 1: Get token
            site_url = f"https://ahrefs.com/backlink-checker/?input={domain}&mode=subdomains"
            token = get_capsolver_token(site_url)
            if not token:
                raise Exception(f"Failed to get verification token for domain: {domain}")
            
            # Step 2: Get signature and validUntil
            signature, valid_until, overview_data = get_signature_and_overview(token, domain)
            if not signature or not valid_until:
                raise Exception(f"Failed to get signature for domain: {domain}")
        
        # Step 3: Get backlinks list
        backlinks = get_backlinks(signature, valid_until, domain)
        return {
            "overview": overview_data,
            "backlinks": backlinks
        }
  • Core helper function that makes the API request to Ahrefs to retrieve the backlinks list using the provided signature and formats the results.
    def get_backlinks(signature: str, valid_until: str, domain: str) -> Optional[List[Any]]:
        if not signature or not valid_until:
            return None
        
        url = "https://ahrefs.com/v4/stGetFreeBacklinksList"
        payload = {
            "reportType": "TopBacklinks",
            "signedInput": {
                "signature": signature,
                "input": {
                    "validUntil": valid_until,
                    "mode": "subdomains",
                    "url": f"{domain}/"
                }
            }
        }
        
        headers = {
            "Content-Type": "application/json"
        }
        
        response = requests.post(url, json=payload, headers=headers)
        if response.status_code != 200:
            return None
        
        data = response.json()
    
        return format_backlinks(data, domain)
  • Helper function to obtain the API signature, validUntil timestamp, and overview data from Ahrefs using the captcha token obtained from CapSolver.
    def get_signature_and_overview(token: str, domain: str) -> Tuple[Optional[str], Optional[str], Optional[Dict[str, Any]]]:
        """
        Get signature and validUntil parameters using the token
        
        Args:
            token: Verification token
            domain: Domain to query
            
        Returns:
            (signature, valid_until, overview_data) tuple, or (None, None, None) if failed
        """
        url = "https://ahrefs.com/v4/stGetFreeBacklinksOverview"
        payload = {
            "captcha": token,
            "mode": "subdomains",
            "url": domain
        }
        
        headers = {
            "Content-Type": "application/json"
        }
        
        response = requests.post(url, json=payload, headers=headers)
        if response.status_code != 200:
            return None, None, None
        
        data = response.json()
        
        try:
            # Assuming data format is always ['Ok', {signature object}]
            if isinstance(data, list) and len(cast(List[Any], data)) > 1:
                second_element: Dict[str, Any] = cast(Dict[str, Any], data[1])
                signature: str = cast(str, second_element['signedInput']['signature'])
                valid_until: str = cast(str, second_element['signedInput']['input']['validUntil'])
                overview_data: Dict[str, Any] = cast(Dict[str, Any], second_element['data'])
                
                # Save the new signature to cache
                save_signature_to_cache(signature, valid_until, overview_data, domain)
                
                return signature, valid_until, overview_data
            else:
                return None, None, None
        except Exception:
            return None, None, None
  • Helper function to load previously cached signature and overview data for a domain, checking if it's still valid (not expired).
    def load_signature_from_cache(domain: str) -> Tuple[Optional[str], Optional[str], Optional[Dict[str, Any]]]:
        """
        Load signature information for a specific domain from local cache file
        Returns the signature and valid_until if cache is valid, otherwise None
        
        Args:
            domain: Domain to query
            
        Returns:
            (signature, valid_until) tuple, or (None, None) if no valid cache
        """
        if not os.path.exists(SIGNATURE_CACHE_FILE):
            return None, None, None
        
        try:
            with open(SIGNATURE_CACHE_FILE, 'r') as f:
                cache_data = json.load(f)
            
            # Check if cache exists for current domain
            if domain not in cache_data:
                return None, None, None
            
            domain_cache = cache_data[domain]
            
            # Check if signature is expired
            valid_until = domain_cache.get("valid_until")
            
            if valid_until:
                # Convert ISO date string to timestamp for comparison
                valid_until_timestamp = iso_to_timestamp(valid_until)
                current_time = time.time()
                
                if current_time < valid_until_timestamp:
                    return domain_cache.get("signature"), valid_until, domain_cache.get("overview_data")
                else:
                    return None, None, None
            else:
                return None, None, None
        except Exception:
            return None, None, None
  • Helper function to obtain captcha token from CapSolver service, required to bypass Ahrefs protections before getting signatures.
    def get_capsolver_token(site_url: str) -> Optional[str]:
        """
        Use CapSolver to solve the captcha and get a token
        
        Args:
            site_url: Site URL to query
            
        Returns:
            Verification token or None if failed
        """
        if not api_key:
            return None
        
        payload = {
            "clientKey": api_key,
            "task": {
                "type": 'AntiTurnstileTaskProxyLess',
                "websiteKey": "0x4AAAAAAAAzi9ITzSN9xKMi",  # site key of your target site: ahrefs.com,
                "websiteURL": site_url,
                "metadata": {
                    "action": ""  # optional
                }
            }
        }
        res = requests.post("https://api.capsolver.com/createTask", json=payload)
        resp = res.json()
        task_id = resp.get("taskId")
        if not task_id:
            return None
     
        while True:
            time.sleep(1)  # delay
            payload = {"clientKey": api_key, "taskId": task_id}
            res = requests.post("https://api.capsolver.com/getTaskResult", json=payload)
            resp = res.json()
            status = resp.get("status")
            if status == "ready":
                token = resp.get("solution", {}).get('token')
                return token
            if status == "failed" or resp.get("errorId"):
                return None

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cnych/backlinks-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server