Skip to content

User

View a list of a user's medias, following and followers

  • user_id - Integer ID of user, example 1903424587
Method Return Description
user_followers(user_id: str, amount: int = 0, order: Optional[FOLLOWERS_ORDER] = None) Dict[int, UserShort] Get dict of followers users (amount=0 - fetch all followers). Use order="date_followed_latest" or order="date_followed_earliest" for mobile follower sorting
user_following(user_id: str, amount: int = 0) Dict[int, UserShort] Get dict of following users (amount=0 - fetch all)
iter_user_followers_v1(user_id: str, amount: int = 0, page_size: int = 200, order: Optional[FOLLOWERS_ORDER] = None) Iterator[UserShort] Stream followers from the private/mobile API without building a full dict
iter_user_following_v1(user_id: str, amount: int = 0, page_size: int = 200) Iterator[UserShort] Stream following users from the private/mobile API without building a full dict
search_followers(user_id: str, query: str) List[UserShort] Search by followers
search_following(user_id: str, query: str) List[UserShort] Search by following
user_info(user_id: str) User Get user info
user_info_by_username(username: str) User Get user info by username
user_about_v1(user_id: str) About Get "About this account" info
user_guides_v1(user_id: int) List[Guide] Get user's guides
user_follow(user_id: str) bool Follow user, or request to follow a private user
user_unfollow(user_id: str) bool Unfollow user
user_block(user_id: str, surface: UserBlockSurface = "profile") bool Block a user from a profile or Direct thread surface
user_unblock(user_id: str, surface: UserBlockSurface = "profile") bool Unblock a user from a profile or Direct thread surface
user_follow_requests(amount: int = 0) List[UserShort] Get pending incoming follow requests
user_follow_request_approve(user_id: str) bool Approve a pending incoming follow request
user_follow_request_decline(user_id: str) bool Decline a pending incoming follow request
user_follow_requests_approve(user_ids: List[str]) Dict[str, bool] Approve pending incoming follow requests
user_follow_requests_decline(user_ids: List[str]) Dict[str, bool] Decline pending incoming follow requests
user_id_from_username(username: str) int Get user_id by username
username_from_user_id(user_id: str) str Get username by user_id
user_remove_follower(user_id: str) bool Remove your follower
user_report(user_id: str, reason: USER_REPORT_REASON = "spam") bool Report a user account. Currently supports the live-verified spam report flow
mute_posts_from_follow(user_id: str) bool Mute posts from following user
unmute_posts_from_follow(user_id: str) bool Unmute posts from following user
mute_stories_from_follow(user_id: str) bool Mute stories from following user
enable_posts_notifications(user_id: str) bool Enable post notifications of user
disable_posts_notifications(user_id: str) bool Disable post notifications of user
enable_videos_notifications(user_id: str) bool Enable videos notifications of user
disable_videos_notifications(user_id: str) bool Disable videos notifications of user
enable_reels_notifications(user_id: str) bool Enable reels notifications of user
disable_reels_notifications(user_id: str) bool Disable reels notifications of user
enable_stories_notifications(user_id: str) bool Enable stories notifications of user
disable_stories_notifications(user_id: str) bool Disable stories notifications of user
close_friend_add(user_id: str) bool Add to Close Friends List
close_friend_remove(user_id: str) bool Remove from Close Friends List
user_suggested_profiles(user_id: str, expand_suggestion: bool = False) dict Suggested profiles ("Suggested for you") for a profile. Wraps chaining and, with expand_suggestion=True, returns the raw fetch_suggestion_details payload (items in current app responses)
address_book_link(contacts: List[AddressBookContact | dict], include: Sequence[str] | str = ("extra_display_name", "thumbnails")) dict Upload/link address book contacts and return Instagram's raw contact-based suggestions response
address_book_unlink() dict Disconnect the uploaded address book from the current account
chaining(user_id: str) dict Suggested users for a profile (discover/chaining/) — same surface as the app's "Suggested for you" carousel
fetch_suggestion_details(user_id: str, chained_ids: str) dict Expanded social-context fields for chained suggestion ids (discover/fetch_suggestion_details/)
discover_recommended_accounts_for_category_v1(user_id: str) dict Business-category-similar accounts: extracts category_id from the target's stream payload, then calls discover/recommended_accounts_for_category/
user_related_profiles_gql(user_id: str) List[UserShort] Related profiles via public GraphQL edge_chaining (legacy query_hash, gated by IG — prefer chaining for reliability)

Option types

Follower sort orders are exposed as FOLLOWERS_ORDER = Literal["date_followed_latest", "date_followed_earliest"]. Pass None to keep Instagram's default follower order.

User block surfaces are exposed as UserBlockSurface = Literal["profile", "direct_thread_info"].

User report reasons are exposed as USER_REPORT_REASON = Literal["spam"].

Type Values Used by
FOLLOWERS_ORDER "date_followed_latest", "date_followed_earliest" user_followers(order=...), user_followers_v1(order=...), iter_user_followers_v1(order=...)
UserBlockSurface "profile", "direct_thread_info" user_block(surface=...), user_unblock(surface=...)
USER_REPORT_REASON "spam" user_report(reason=...)

Lookup helpers:

Method Return Description
user_short_gql(user_id: str, use_cache: bool = True) UserShort Short user info with current GraphQL/web-profile fallback chain
username_from_user_id_gql(user_id: str) str Resolve username from user id using the same fallback chain

Streamed profile fetch (raw payloads, app-side surface):

Method Return Description
user_stream_by_id_v1(user_id: str) dict Streamed profile envelope by pk (users/{user_id}/info_stream/)
user_stream_by_username_v1(username: str) dict Streamed profile envelope by username (users/{username}/usernameinfo_stream/)
user_stream_by_id_flat(user_id: str) dict Same as _v1 but stream_rows[*].user partials merged into a single dict
user_stream_by_username_flat(username: str) dict Same as _v1 but stream_rows[*].user partials merged into a single dict
user_web_profile_info_v1(username: str) dict users/web_profile_info/?username=... via the private host (logged-in session, bypasses public-side rate limiting)
feed_user_stream_item(item_id: str, is_pull_to_refresh: bool = False) dict Raw streamed feed payload for a user/profile grid item

Low level methods:

Method Return Description
user_followers_gql_chunk(user_id: str, max_amount: int = 0, end_cursor: str = None) Tuple[List[UserShort], str] Get user's followers information by Public Graphql API and end_cursor
user_followers_gql(user_id: str, amount: int = 0) List[UserShort] Get user's followers information by Public Graphql API
user_followers_v1_chunk(user_id: str, max_amount: int = 0, max_id: str = "", order: Optional[FOLLOWERS_ORDER] = None) Tuple[List[UserShort], str] Get user's followers information by Private Mobile API and max_id (cursor). Supports date_followed_latest and date_followed_earliest
user_followers_v1(user_id: str, amount: int = 0, order: Optional[FOLLOWERS_ORDER] = None) List[UserShort] Get user's followers information by Private Mobile API. Supports date_followed_latest and date_followed_earliest
iter_user_followers_v1(user_id: str, amount: int = 0, page_size: int = 200, order: Optional[FOLLOWERS_ORDER] = None) Iterator[UserShort] Stream followers page by page through user_followers_v1_chunk()
user_followers_private_gql_chunk(user_id: str, max_amount: int = 0, max_id: str = None, rank_token: str = None, order: Optional[FOLLOWERS_ORDER] = None) Tuple[List[UserShort], str] Get user's followers through the private mobile GraphQL FollowersList surface and max_id cursor
user_followers_private_gql(user_id: str, amount: int = 0, rank_token: str = None, order: Optional[FOLLOWERS_ORDER] = None) List[UserShort] Get user's followers through the private mobile GraphQL FollowersList surface
user_following_v1(user_id: str, amount: int = 0) List[UserShort] Get user's following users information by Private Mobile API
iter_user_following_v1(user_id: str, amount: int = 0, page_size: int = 200) Iterator[UserShort] Stream following users page by page through user_following_v1_chunk()
user_following_private_gql_chunk(user_id: str, max_amount: int = 0, max_id: str = None, rank_token: str = None, order: Optional[FOLLOWERS_ORDER] = None) Tuple[List[UserShort], str] Get user's following users through the private mobile GraphQL FollowingList surface and max_id cursor
user_following_private_gql(user_id: str, amount: int = 0, rank_token: str = None, order: Optional[FOLLOWERS_ORDER] = None) List[UserShort] Get user's following users through the private mobile GraphQL FollowingList surface
user_follow_requests_chunk(max_amount: int = 0, max_id: str = "") Tuple[List[UserShort], str] Get pending incoming follow requests by Private Mobile API and max_id
user_following_gql(user_id: str, amount: int = 0) List[UserShort] Get user's following information by Public Graphql API
search_followers_v1(user_id: str, query: str) List[UserShort] Search by followers by Private Mobile API
search_following_v1(user_id: str, query: str) List[UserShort] Search by following by Private Mobile API
user_info_v2_gql(user_id: str) User Profile lookup through current doc_id GraphQL
user_info_by_username_v2_gql(username: str) User Resolve username through doc_id search, then fetch profile
private_graphql_followers_list(user_id: str, rank_token: str, ..., order: Optional[FOLLOWERS_ORDER] = None) dict Raw private mobile GraphQL followers list. Supports date_followed_latest and date_followed_earliest
private_graphql_following_list(user_id: str, rank_token: str, ..., order: Optional[FOLLOWERS_ORDER] = None) dict Raw private mobile GraphQL following list. Supports mobile order when accepted by Instagram
private_graphql_clips_profile(target_user_id: str, ...) dict Raw private mobile GraphQL profile Reels stream
private_graphql_inbox_tray_for_user(user_id: str, ...) dict Raw private mobile GraphQL inbox tray query

The batch follow request helpers call the single-user approve/decline endpoints for each user_id; they do not implement an auto-approval policy.

user_follow() returns True only when it sends a new follow action and Instagram reports either an immediate follow or a new outgoing follow request for a private account. It returns False when the current account already follows the target or already has a pending outgoing follow request. Use user_friendship_v1() when you need to distinguish following from outgoing_request.

UserShort objects returned from private GraphQL follow-list payloads preserve selected v2-only fields when Instagram sends them: friendship_status, profile_pic_id, fbid_v2, interop_messaging_user_fbid, strong_id__, and raw account_badges. The legacy latest_reel_media property is also populated from Instagram's current 1llatest_reel_media key.

user_report(user_id, reason="spam") follows Instagram's current mobile FRX report flow for account spam reports and submits the report. reason uses USER_REPORT_REASON and currently supports "spam". This is a real account action; use it only for accounts you actually intend to report. Unsupported reasons raise ValueError until their FRX tag paths are captured and tested.

Example:

>>> cl.user_followers(cl.user_id).keys()
dict_keys([5563084402, 43848984510, 1498977320, ...])

>>> cl.user_following(cl.user_id)
{
  8530498223: UserShort(
    pk=8530498223,
    username="something",
    full_name="Example description",
    profile_pic_url=HttpUrl(
      'https://instagram.frix7-1.fna.fbcdn.net/v/t5...9217617140_n.jpg',
      scheme='https',
      host='instagram.frix7-1.fna.fbcdn.net',
      ...
    ),
  ),
  49114585: UserShort(
    pk=49114585,
    username='gx1000',
    full_name='GX1000',
    profile_pic_url=HttpUrl(
      'https://scontent-hel3-1.cdninstagram.com/v/t51.2885-19/10388...jpg',
      scheme='https',
      host='scontent-hel3-1.cdninstagram.com',
      ...
    )
  ),
  ...
}

>>> cl.user_info_by_username('example').dict()
{'pk': 1903424587,
 'username': 'example',
 'full_name': 'Example Example',
 'is_private': False,
 'profile_pic_url': HttpUrl('https://scontent-hel3-1.cdninstagram.com/v/t51.2885-19/s150x150/123884060_803537687159702_2508263208740189974_n.jpg?...', scheme='https', host='scontent-hel3-1.cdninstagram.com', tld='com', host_type='domain', ...'),
 'is_verified': False,
 'media_count': 102,
 'follower_count': 576,
 'following_count': 538,
 'biography': 'Engineer: Python, JavaScript, Erlang',
 'external_url': HttpUrl('https://example.org/', scheme='https', host='example.org', tld='com', host_type='domain', path='/'),
 'is_business': False}

Sorted followers:

latest_followers = cl.user_followers(cl.user_id, amount=50, order="date_followed_latest")
earliest_followers = cl.user_followers_v1(cl.user_id, amount=50, order="date_followed_earliest")

Streaming followers/following:

for follower in cl.iter_user_followers_v1(cl.user_id, amount=1000, page_size=100, order="date_followed_latest"):
    print(follower.pk, follower.username)

for user in cl.iter_user_following_v1(cl.user_id, amount=1000, page_size=100):
    print(user.pk, user.username)

Raw private GraphQL helpers expose the same mobile order variable for callers that need the FollowersList/FollowingList payload directly:

payload = cl.private_graphql_followers_list(cl.user_id, cl.rank_token, order="date_followed_latest")

Use user_followers_private_gql() when you want the current mobile GraphQL followers list parsed into UserShort objects:

followers = cl.user_followers_private_gql(cl.user_id, amount=50, order="date_followed_latest")

user_following_private_gql() is the matching helper for the following list:

following = cl.user_following_private_gql(cl.user_id, amount=50)

When the account is authorized, user_followers() and user_following() prefer the private mobile API and automatically retry through the private mobile GraphQL follow-list surface (FollowersList/FollowingList) when the private endpoint fails or the followers list is limited. The legacy public GraphQL query is only used as the last resort, because Instagram returns an empty edges list for the legacy followers/following query hash.

Example: We go around the list of our followers and unfollow from them:

from instagrapi import Client

cl = Client()
cl.login(USERNAME, PASSWORD)

followers = cl.user_followers(cl.user_id)
for user_id in followers.keys():
    cl.user_unfollow(user_id)

Example: Suggested profiles ("Suggested for you") for a target user:

from instagrapi import Client
from instagrapi.exceptions import InvalidTargetUser

cl = Client()
cl.login(USERNAME, PASSWORD)

user_id = cl.user_id_from_username("example")
try:
    suggested = cl.user_suggested_profiles(user_id)
    # Expanded social-context fields (current app responses expose them under "items"):
    detailed = cl.user_suggested_profiles(user_id, expand_suggestion=True)
except InvalidTargetUser:
    # Instagram refuses chaining for locked-down / private targets
    suggested = {"users": []}

Tip:

  • user_info(), user_info_by_username(), user_id_from_username(), and username_from_user_id() use private/mobile lookup first when the client has authorization data or a saved sessionid, then fall back to public/web lookup. Without authorization, these high-level helpers keep the public/web-first behavior. Explicit _gql methods still call the public/web path directly.
  • user_followers() and user_following() use private/mobile lookup first when the client has authorization data or a saved sessionid, then fall back to public/web lookup. Without authorization, these high-level helpers keep the public/web-first behavior. Explicit _gql methods still call the public/web path directly.
  • Use iter_user_followers_v1() and iter_user_following_v1() when you need to process large follow lists incrementally instead of keeping the full result in memory.