Skip to main content
Glama
Arindam200

Reddit MCP Server

get_submission_by_url

Retrieve structured Reddit post data by providing its URL, including optional comments and metadata for analysis.

Instructions

Get a Reddit submission by its URL.

Args:
    url: The URL of the Reddit submission to retrieve
    include_comments: If True, load and return the full comment forest for the post
    comment_replace_more_limit: Limit for replacing "MoreComments" objects (0 for none, None for all)

Returns:
    Dictionary containing structured submission information with the following structure:
    {
        'id': str,  # Submission ID (e.g., 'abc123')
        'title': str,  # Submission title
        'author': str,  # Author's username or '[deleted]' if deleted
        'subreddit': str,  # Subreddit name
        'score': int,  # Post score (upvotes - downvotes)
        'upvote_ratio': float,  # Ratio of upvotes to total votes
        'num_comments': int,  # Number of comments
        'created_utc': float,  # Post creation timestamp (UTC)
        'url': str,  # Full URL to the post
        'permalink': str,  # Relative URL to the post
        'is_self': bool,  # Whether it's a self (text) post
        'selftext': str,  # Content of self post (if any)
        'selftext_html': Optional[str],  # HTML formatted content
        'link_url': str,  # URL for link posts (if any)
        'domain': str,  # Domain of the linked content
        'over_18': bool,  # Whether marked as NSFW
        'spoiler': bool,  # Whether marked as spoiler
        'stickied': bool,  # Whether stickied in the subreddit
        'locked': bool,  # Whether comments are locked
        'archived': bool,  # Whether the post is archived
        'distinguished': Optional[str],  # Distinguishing type (e.g., 'moderator')
        'flair': Optional[Dict],  # Post flair information if any
        'media': Optional[Dict],  # Media information if any
        'preview': Optional[Dict],  # Preview information if available
        'awards': List[Dict],  # List of awards received
        'comments': Optional[List[Dict]],  # present if include_comments is True
        'metadata': {
            'fetched_at': float,  # Timestamp when data was fetched
            'subreddit_id': str,  # Subreddit full ID
            'author_id': str,  # Author's full ID if available
            'is_original_content': bool,  # Whether marked as OC
            'is_meta': bool,  # Whether marked as meta
            'is_crosspostable': bool,  # Whether can be crossposted
            'is_reddit_media_domain': bool,  # Whether media is hosted on Reddit
            'is_robot_indexable': bool,  # Whether search engines should index
            'is_created_from_ads_ui': bool,  # Whether created via ads UI
            'is_video': bool,  # Whether the post is a video
            'pinned': bool,  # Whether the post is pinned in the subreddit
            'gilded': int,  # Number of times gilded
            'total_awards_received': int,  # Total number of awards received
            'view_count': Optional[int],  # View count if available
            'visited': bool,  # Whether the current user has visited
        }
    }

Raises:
    ValueError: If URL is invalid or submission not found
    RuntimeError: For other errors during the operation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYes
include_commentsNo
comment_replace_more_limitNo

Implementation Reference

  • The primary handler function decorated with @mcp.tool() that implements the get_submission_by_url tool. It fetches a Reddit submission using PRAW client.submission(url=url), extracts and structures all relevant metadata, optionally loads and serializes the comment tree, and returns a comprehensive dictionary with post details, flair, awards, media, and metadata.
    def get_submission_by_url(url: str, include_comments: bool = False, comment_replace_more_limit: int = 0) -> Dict[str, Any]:
        """Get a Reddit submission by its URL.
    
        Args:
            url: The URL of the Reddit submission to retrieve
            include_comments: If True, load and return the full comment forest for the post
            comment_replace_more_limit: Limit for replacing "MoreComments" objects (0 for none, None for all)
    
        Returns:
            Dictionary containing structured submission information with the following structure:
            {
                'id': str,  # Submission ID (e.g., 'abc123')
                'title': str,  # Submission title
                'author': str,  # Author's username or '[deleted]' if deleted
                'subreddit': str,  # Subreddit name
                'score': int,  # Post score (upvotes - downvotes)
                'upvote_ratio': float,  # Ratio of upvotes to total votes
                'num_comments': int,  # Number of comments
                'created_utc': float,  # Post creation timestamp (UTC)
                'url': str,  # Full URL to the post
                'permalink': str,  # Relative URL to the post
                'is_self': bool,  # Whether it's a self (text) post
                'selftext': str,  # Content of self post (if any)
                'selftext_html': Optional[str],  # HTML formatted content
                'link_url': str,  # URL for link posts (if any)
                'domain': str,  # Domain of the linked content
                'over_18': bool,  # Whether marked as NSFW
                'spoiler': bool,  # Whether marked as spoiler
                'stickied': bool,  # Whether stickied in the subreddit
                'locked': bool,  # Whether comments are locked
                'archived': bool,  # Whether the post is archived
                'distinguished': Optional[str],  # Distinguishing type (e.g., 'moderator')
                'flair': Optional[Dict],  # Post flair information if any
                'media': Optional[Dict],  # Media information if any
                'preview': Optional[Dict],  # Preview information if available
                'awards': List[Dict],  # List of awards received
                'comments': Optional[List[Dict]],  # present if include_comments is True
                'metadata': {
                    'fetched_at': float,  # Timestamp when data was fetched
                    'subreddit_id': str,  # Subreddit full ID
                    'author_id': str,  # Author's full ID if available
                    'is_original_content': bool,  # Whether marked as OC
                    'is_meta': bool,  # Whether marked as meta
                    'is_crosspostable': bool,  # Whether can be crossposted
                    'is_reddit_media_domain': bool,  # Whether media is hosted on Reddit
                    'is_robot_indexable': bool,  # Whether search engines should index
                    'is_created_from_ads_ui': bool,  # Whether created via ads UI
                    'is_video': bool,  # Whether the post is a video
                    'pinned': bool,  # Whether the post is pinned in the subreddit
                    'gilded': int,  # Number of times gilded
                    'total_awards_received': int,  # Total number of awards received
                    'view_count': Optional[int],  # View count if available
                    'visited': bool,  # Whether the current user has visited
                }
            }
    
        Raises:
            ValueError: If URL is invalid or submission not found
            RuntimeError: For other errors during the operation
        """
        manager = RedditClientManager()
        if not manager.client:
            raise RuntimeError("Reddit client not initialized")
    
        if not url or not isinstance(url, str):
            raise ValueError("URL is required")
        if not url.startswith(("http://", "https://")):
            raise ValueError("URL must start with http:// or https://")
    
        try:
            logger.info(f"Getting submission from URL: {url} (include_comments={include_comments})")
    
            # Create submission from URL
            submission = manager.client.submission(url=url)
    
            # Force fetch submission data to verify it exists and get all attributes
            submission.title  # This will raise if submission doesn't exist
    
            # Get basic submission data with error handling
            submission_data = {
                "id": submission.id,
                "title": submission.title,
                "author": str(submission.author)
                if hasattr(submission, "author") and submission.author
                else "[deleted]",
                "subreddit": submission.subreddit.display_name
                if hasattr(submission, "subreddit")
                else "unknown",
                "score": getattr(submission, "score", 0),
                "upvote_ratio": getattr(submission, "upvote_ratio", 0.0),
                "num_comments": getattr(submission, "num_comments", 0),
                "created_utc": submission.created_utc,
                "url": f"https://www.reddit.com{submission.permalink}"
                if hasattr(submission, "permalink")
                else url,
                "permalink": getattr(submission, "permalink", f"/comments/{submission.id}"),
                "is_self": getattr(submission, "is_self", False),
                "selftext": getattr(submission, "selftext", ""),
                "selftext_html": getattr(submission, "selftext_html", None),
                "link_url": getattr(submission, "url", ""),
                "domain": getattr(submission, "domain", ""),
                "over_18": getattr(submission, "over_18", False),
                "spoiler": getattr(submission, "spoiler", False),
                "stickied": getattr(submission, "stickied", False),
                "locked": getattr(submission, "locked", False),
                "archived": getattr(submission, "archived", False),
                "distinguished": getattr(submission, "distinguished", None),
                "flair": None,
                "media": getattr(submission, "media", None),
                "preview": getattr(submission, "preview", None),
                "awards": [],
            }
    
            # Add flair information if available
            if hasattr(submission, "link_flair_text") and submission.link_flair_text:
                submission_data["flair"] = {
                    "text": submission.link_flair_text,
                    "css_class": getattr(submission, "link_flair_css_class", ""),
                    "template_id": getattr(submission, "link_flair_template_id", None),
                    "text_color": getattr(submission, "link_flair_text_color", None),
                    "background_color": getattr(
                        submission, "link_flair_background_color", None
                    ),
                }
    
            # Add awards information if available
            if hasattr(submission, "all_awardings"):
                submission_data["awards"] = [
                    {
                        "id": award.get("id"),
                        "name": award.get("name"),
                        "description": award.get("description"),
                        "coin_price": award.get("coin_price", 0),
                        "coin_reward": award.get("coin_reward", 0),
                        "icon_url": award.get("icon_url"),
                        "count": award.get("count", 1),
                    }
                    for award in submission.all_awardings
                ]
    
            # Add comments if requested
            if include_comments:
                try:
                    # Resolve all MoreComments to get the complete tree
                    submission.comments.replace_more(limit=comment_replace_more_limit)
    
                    top_level_comments = [
                        c
                        for c in submission.comments
                        if isinstance(c, praw.models.Comment)
                    ]
    
                    submission_data["comments"] = [
                        _serialize_comment_tree(c) for c in top_level_comments
                    ]
                except Exception as comments_error:
                    logger.exception(f"Error loading comments for submission {submission.id}")
                    submission_data["comments"] = []
    
            # Add metadata
            submission_data["metadata"] = {
                "fetched_at": time.time(),
                "subreddit_id": getattr(submission.subreddit, "id", "")
                if hasattr(submission, "subreddit")
                else "",
                "author_id": f"t2_{submission.author.id}"
                if hasattr(submission, "author")
                and submission.author
                and hasattr(submission.author, "id")
                else None,
                "is_original_content": getattr(submission, "is_original_content", False),
                "is_meta": getattr(submission, "is_meta", False),
                "is_crosspostable": getattr(submission, "is_crosspostable", False),
                "is_reddit_media_domain": getattr(
                    submission, "is_reddit_media_domain", False
                ),
                "is_robot_indexable": getattr(submission, "is_robot_indexable", True),
                "is_created_from_ads_ui": getattr(
                    submission, "is_created_from_ads_ui", False
                ),
                "is_video": getattr(submission, "is_video", False),
                "pinned": getattr(submission, "pinned", False),
                "gilded": getattr(submission, "gilded", 0),
                "total_awards_received": getattr(submission, "total_awards_received", 0),
                "view_count": getattr(submission, "view_count", None),
                "visited": getattr(submission, "visited", False),
            }
    
            return submission_data
    
        except Exception as e:
            logger.error(f"Error in get_submission_by_url: {e}")
            if "404" in str(e) or "not found" in str(e).lower():
                raise ValueError(f"Submission not found at URL: {url}") from e
            if "403" in str(e) or "forbidden" in str(e).lower():
                raise ValueError(
                    f"Not authorized to access submission at URL: {url}"
                ) from e
            if isinstance(e, (ValueError, RuntimeError)):
                raise
            raise RuntimeError(f"Failed to get submission by URL: {e}") from e

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/Arindam200/reddit-mcp'

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