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

Code before:
    urlencode_postdata,
)

_ENCODING_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'


def _pk_to_id(media_id):
    """Source: https://stackoverflow.com/questions/24437823/getting-instagram-post-url-from-media-id"""
    pk = int(str(media_id).split('_')[0])
    return encode_base_n(pk, table=_ENCODING_CHARS)


def _id_to_pk(shortcode):
    """Covert a shortcode to a numeric value"""
    return decode_base_n(shortcode[:11], table=_ENCODING_CHARS)


class InstagramBaseIE(InfoExtractor):
    _NETRC_MACHINE = 'instagram'
    _IS_LOGGED_IN = False

    _API_BASE_URL = 'https://i.instagram.com/api/v1'
    _LOGIN_URL = 'https://www.instagram.com/accounts/login'

    def _api_headers(self):
        return {
            'X-IG-App-ID': self._configuration_arg('app_id', '936619743392459')[0],
            'X-ASBD-ID': '198387',
            'X-IG-WWW-Claim': '0',
            'Origin': 'https://www.instagram.com',
            'Accept': '*/*',
        }

    def _perform_login(self, username, password):
        if self._IS_LOGGED_IN:
            return

        login_webpage = self._download_webpage(
            self._LOGIN_URL, None, note='Downloading login webpage', errnote='Failed to download login webpage')

        shared_data = self._parse_json(self._search_regex(
            r'window\._sharedData\s*=\s*({.+?});', login_webpage, 'shared data', default='{}'), None)

        login = self._download_json(
            f'{self._LOGIN_URL}/ajax/', None, note='Logging in', headers={
                **self._api_headers(),
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRFToken': shared_data['config']['csrf_token'],
                'X-Instagram-AJAX': shared_data['rollout_hash'],
                'Referer': 'https://www.instagram.com/',
            }, data=urlencode_postdata({

Review comment (suggestion):
I'd prefer to do this, and then remove all the `()`s below
```suggestion
    @property
    def _api_headers(self):
```

Code after:
    urlencode_postdata,
)

_ENCODING_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'


def _pk_to_id(media_id):
    """Source: https://stackoverflow.com/questions/24437823/getting-instagram-post-url-from-media-id"""
    pk = int(str(media_id).split('_')[0])
    return encode_base_n(pk, table=_ENCODING_CHARS)


def _id_to_pk(shortcode):
    """Covert a shortcode to a numeric value"""
    return decode_base_n(shortcode[:11], table=_ENCODING_CHARS)


class InstagramBaseIE(InfoExtractor):
    _NETRC_MACHINE = 'instagram'
    _IS_LOGGED_IN = False

    _API_BASE_URL = 'https://i.instagram.com/api/v1'
    _LOGIN_URL = 'https://www.instagram.com/accounts/login'

    @property
    def _api_headers(self):
        return {
            'X-IG-App-ID': self._configuration_arg('app_id', ['936619743392459'], ie_key=InstagramIE)[0],
            'X-ASBD-ID': '198387',
            'X-IG-WWW-Claim': '0',
            'Origin': 'https://www.instagram.com',
            'Accept': '*/*',
        }

    def _perform_login(self, username, password):
        if self._IS_LOGGED_IN:
            return

        login_webpage = self._download_webpage(
            self._LOGIN_URL, None, note='Downloading login webpage', errnote='Failed to download login webpage')

        shared_data = self._parse_json(self._search_regex(
            r'window\._sharedData\s*=\s*({.+?});', login_webpage, 'shared data', default='{}'), None)

        login = self._download_json(
            f'{self._LOGIN_URL}/ajax/', None, note='Logging in', headers={
                **self._api_headers,
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRFToken': shared_data['config']['csrf_token'],
                'X-Instagram-AJAX': shared_data['rollout_hash'],
                'Referer': 'https://www.instagram.com/',