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

Code before:
        }


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).groups()
        story_info = self._download_webpage(url, story_id or username)
        user_info = self._search_json(r'"user":', story_info, 'user info', story_id or username, fatal=False)
        if not user_info:
            self.raise_login_required('This content is unreachable')

        user_id = traverse_obj(user_info, 'pk', 'id', expected_type=str)
        if username == 'highlights':
            story_info_url = f'highlight:{story_id}'
            if not story_id:  # story id is only mandatory for highlights
                raise ExtractorError('Missing highlight id')
        else:
            if not user_id:  # user id is only mandatory for non-highlights
                raise ExtractorError('Unable to extract user id')
            story_info_url = user_id

        videos = traverse_obj(self._download_json(
            f'{self._API_BASE_URL}/feed/reels_media/?reel_ids={story_info_url}',
            story_id or username, errnote=False, fatal=False, headers=self._API_HEADERS), 'reels')
        if not videos:
            self.raise_login_required('You need to log in to access this content')

        full_name = traverse_obj(videos, (f'highlight:{story_id}', 'user', 'full_name'), (user_id, 'user', 'full_name'))
        story_title = traverse_obj(videos, (f'highlight:{story_id}', 'title'))
        if not story_title:
            story_title = f'Story by {username}'

        highlights = traverse_obj(videos, (f'highlight:{story_id}', 'items'), (user_id, 'items'))

Review comment (suggestion):
```suggestion
        story_info = self._download_webpage(url, display_id)
        user_info = self._search_json(r'"user":', story_info, 'user info', display_id, fatal=False)
```

Code after:
        }


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:
            self.raise_login_required('This content is unreachable')

        user_id = traverse_obj(user_info, 'pk', 'id', expected_type=str)
        if username == 'highlights':
            story_info_url = f'highlight:{story_id}'
        else:
            if not user_id:  # user id is only mandatory for non-highlights
                raise ExtractorError('Unable to extract user id')
            story_info_url = user_id

        videos = traverse_obj(self._download_json(
            f'{self._API_BASE_URL}/feed/reels_media/?reel_ids={story_info_url}',
            display_id, errnote=False, fatal=False, headers=self._API_HEADERS), 'reels')
        if not videos:
            self.raise_login_required('You need to log in to access this content')
        user_info = traverse_obj(videos, (user_id, 'user', {dict})) or {}

        full_name = traverse_obj(videos, (f'highlight:{story_id}', 'user', 'full_name'), (user_id, 'user', 'full_name'))
        story_title = traverse_obj(videos, (f'highlight:{story_id}', 'title'))
        if not story_title:
            story_title = f'Story by {username}'