Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/instagram.py (Python)

Code before:
        'params': {
            'extract_flat': True,
            'skip_download': True,
            'playlistend': 50,
        },
    }]

    _QUERY_HASH = ('f92f56d47dc7a55b606908374b43a314',)

    @staticmethod
    def _parse_timeline_from(data):
        # extracts the media timeline data from a GraphQL result
        return data['data']['hashtag']['edge_hashtag_to_media']

    @staticmethod
    def _query_vars_for(data):
        # returns a dictionary of variables to add to the timeline query based
        # on the GraphQL of the original page
        return {
            'tag_name':
                data['entry_data']['TagPage'][0]['graphql']['hashtag']['name'],
        }


class InstagramStoryIE(InstagramBaseIE):
    _VALID_URL = r'https?://(?:www\.)?instagram\.com/stories/(?P<user>[^/]+)(?:/(?P<id>\d+))?'
    IE_NAME = 'instagram:story'

    _TESTS = [{
        'url': 'https://www.instagram.com/stories/highlights/18090946048123978/',
        'info_dict': {
            'id': '18090946048123978',
            'title': 'Rare',
        },
        'playlist_mincount': 50,
    }, {
        'url': 'https://www.instagram.com/stories/fruits_zipper/3570766765028588805/',
        'only_matching': True,
    }, {
        'url': 'https://www.instagram.com/stories/fruits_zipper',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        username, story_id = self._match_valid_url(url).group('user', 'id')
        if username == 'highlights' and not story_id:  # story id is only mandatory for highlights
            raise ExtractorError('Missing highlight id')
        display_id = story_id or username
        story_info = self._download_webpage(url, display_id)
        user_info = self._search_json(r'"user":', story_info, 'user info', display_id, fatal=False)
        if not user_info:

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:www\.)?instagram\.com/stories/(?P<user>[^/?#]+)(?:/(?P<id>\d+))?'
```

Code after:
        'params': {
            'extract_flat': True,
            'skip_download': True,
            'playlistend': 50,
        },
    }]

    _QUERY_HASH = ('f92f56d47dc7a55b606908374b43a314',)

    @staticmethod
    def _parse_timeline_from(data):
        # extracts the media timeline data from a GraphQL result
        return data['data']['hashtag']['edge_hashtag_to_media']

    @staticmethod
    def _query_vars_for(data):
        # returns a dictionary of variables to add to the timeline query based
        # on the GraphQL of the original page
        return {
            'tag_name':
                data['entry_data']['TagPage'][0]['graphql']['hashtag']['name'],
        }


class InstagramStoryIE(InstagramBaseIE):
    _VALID_URL = r'https?://(?:www\.)?instagram\.com/stories/(?P<user>[^/?#]+)(?:/(?P<id>\d+))?'
    IE_NAME = 'instagram:story'

    _TESTS = [{
        'url': 'https://www.instagram.com/stories/highlights/18090946048123978/',
        'info_dict': {
            'id': '18090946048123978',
            'title': 'Rare',
        },
        'playlist_mincount': 50,
    }, {
        'url': 'https://www.instagram.com/stories/fruits_zipper/3570766765028588805/',
        'only_matching': True,
    }, {
        'url': 'https://www.instagram.com/stories/fruits_zipper',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        username, story_id = self._match_valid_url(url).group('user', 'id')
        if username == 'highlights' and not story_id:  # story id is only mandatory for highlights
            raise ExtractorError('Input URL is missing a highlight ID', expected=True)
        display_id = story_id or username
        story_info = self._download_webpage(url, display_id)
        user_info = self._search_json(r'"user":', story_info, 'user info', display_id, fatal=False)
        if not user_info: