instagrapi

🔥 The fastest and powerful Python library for Instagram Private API 2026 with HikerAPI SaaS

View on GitHub

Story

Method Return Description
user_stories(user_id: str, amount: int = None) List[Story] Get list of stories by user_id; public/web first, private fallback when authenticated
story_info(story_pk: int, use_cache: bool = True) Story Return story info
story_delete(story_pk: int) bool Delete story
story_seen(story_pks: List[int], skipped_story_pks: List[int]) bool Mark a story as seen
story_pk_from_url(url: str) int Get Story (media) PK from URL
story_download(story_pk: int, filename: str = “”, folder: Path = “”) Path Download story media by media_type
story_download_by_url(url: str, filename: str = “”, folder: Path = “”) Path Download story media using URL to file (mp4 or jpg)
story_viewers(story_pk: int, amount: int = 20) List[UserShort] List of story viewers (via Private API)
archive_story_days(amount: int = 0, include_memories: bool = True) List[StoryArchiveDay] Get your story archive day shells
archive_stories(amount: int = 0) List[Story] Get your archived stories
story_like(story_id: str, revert: bool = False) bool Like a story
story_unlike(story_id: str) bool Unlike a story

Example:

>>> cl.story_download(cl.story_pk_from_url('https://www.instagram.com/stories/example/2581281926631793076/'))
PosixPath('/app/189361307_229642088942817_9180243596650100310_n.mp4')

>>> s = cl.story_info(2581281926631793076)

>>> cl.story_download_by_url(s.video_url)  # url to mp4 file
PosixPath('/app/189361307_229642088942817_9180243596650100310_n.mp4')

>>> cl.story_download_by_url(s.thumbnail_url)  # URL to jpg file
PosixPath('/app/191260083_2908005872746895_8988438451809588865_n.jpg')

>>> days = cl.archive_story_days(amount=1)
>>> days[0].id
'archiveDay:1710000000000'

>>> archived = cl.archive_stories(amount=5)
>>> [story.pk for story in archived]
['3155832952940083788']

Story Archive

archive_story_days() returns StoryArchiveDay objects for the logged-in account’s story archive. Use archive_stories() when you need the story media items from those archive days.

Low level methods:

Method Return Description
archive_story_days_v1(amount: int = 0, include_memories: bool = True) List[StoryArchiveDay] Get story archive days via private mobile API
archive_story_days_paginated_v1(amount: int = 0, end_cursor: str = “”, include_memories: bool = True, reel_id: str = “”) Tuple[List[StoryArchiveDay], str] Get one private API page of story archive days
archive_stories_v1(amount: int = 0) List[Story] Get archived stories via private mobile API

Upload Stories

Upload medias to your stories.

The story file should be at 9:16 resolution (e.g. 720x1280). If you have a different resolution, then you need to prepare a file or use the StoryBuilder, which is written about below.

Common arguments:

Method Return Description
photo_upload_to_story(path: Path, caption: str = “”, upload_id: str = “”, mentions: List[StoryMention] = [], locations: List[StoryLocation] = [], links: List[StoryLink] = [], hashtags: List[StoryHashtag] = [], stickers: List[StorySticker] = [], medias: List[StoryMedia] = [], polls: List[StoryPoll] = [], extra_data: Dict[str, str] = {}) Story Upload photo to story
video_upload_to_story(path: Path, caption: str = “”, thumbnail: Path = None, mentions: List[StoryMention] = [], locations: List[StoryLocation] = [], links: List[StoryLink] = [], hashtags: List[StoryHashtag] = [], stickers: List[StorySticker] = [], medias: List[StoryMedia] = [], polls: List[StoryPoll] = [], extra_data: Dict[str, str] = {}) Story Upload video to story
media_share_to_story(media_id: str, background: Path = None, caption: str = “”) Story Share an existing post to your story with a generated or provided background
photo_upload_to_story_with_music(path: Path, caption: str, track: Track or dict, thumbnail: Path = None, duration: float = 15.0, extra_data: Dict = {}) Story Upload photo to story as a short video with the selected music track muxed into it
video_upload_to_story_with_music(path: Path, caption: str, track: Track or dict, thumbnail: Path = None, extra_data: Dict = {}) Story Upload video to story with the selected music track muxed into it
story_music_extra_data(track: Track or dict, extra_data: Dict = {}) dict Build Story music configure fields for manual story upload extra_data

In extra_data, you can pass additional story settings, for example:

Method Type Description
audience String Publish story for close friends {"audience": "besties"}

Notes:

Examples:

from instagrapi import Client
from instagrapi.types import StoryMention, StoryMedia, StoryLink, StoryHashtag

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

media_pk = cl.media_pk_from_url('https://www.instagram.com/p/CGgDsi7JQdS/')
media_path = cl.video_download(media_pk)
example = cl.user_info_by_username('example')
hashtag = cl.hashtag_info('dhbastards')

cl.video_upload_to_story(
    media_path,
    "Credits @example",
    mentions=[StoryMention(user=example, x=0.49892962, y=0.703125, width=0.8333333333333334, height=0.125)],
    links=[StoryLink(webUri='https://github.com/subzeroid/instagrapi')],
    hashtags=[StoryHashtag(hashtag=hashtag, x=0.23, y=0.32, width=0.5, height=0.22)],
    medias=[StoryMedia(media_pk=media_pk, x=0.5, y=0.5, width=0.6, height=0.8)],
    polls=[StoryPoll(x = 0.5, y = 0.5, width = 0.7, height = 0.5, question = "Question", options = ["Option 1", "Option 2", "Option 3"])],
)

cl.media_share_to_story(media_pk, caption="Shared to story")

Upload Story with Music

Story music upload works by rendering an MP4 locally and then publishing it with the normal story upload flow.

pip install "instagrapi[video]"
pip install --no-deps "moviepy==2.2.1"
from pathlib import Path

track = cl.search_music("song name")[0]

cl.video_upload_to_story_with_music(
    Path("/app/story.mp4"),
    "Credits @example",
    track,
    thumbnail=Path("/app/story-thumb.jpg"),
)

cl.photo_upload_to_story_with_music(
    Path("/app/story.jpg"),
    "Credits @example",
    track,
    duration=7,
)

Build Story to Upload

If you want to format your story correctly (correct resolution, user mentions, etc) use StoryBuilder. StoryBuilder renders media with MoviePy and ffmpeg, so install the optional video dependencies first:

pip install "instagrapi[video]"
pip install --no-deps "moviepy==2.2.1"

MoviePy 2.2.1 currently declares Pillow<12, but instagrapi keeps Pillow>=12.2.0 for security fixes; the --no-deps install keeps the safe Pillow version. Older MoviePy 1.x imports such as moviepy.editor and clip methods such as set_duration, set_position, resize, and subclip are not supported by instagrapi’s video helpers.

Method Return Description
StoryBuilder.build_clip(clip: moviepy.Clip, max_duration: int = 0) StoryBuild Build CompositeVideoClip with background and mentioned users. Return MP4 file and mentions with coordinates
StoryBuilder.video(max_duration: int = 0) StoryBuild Call build_clip(VideoClip, max_duration)
StoryBuilder.photo(max_duration: int = 0) StoryBuild Call build_clip(ImageClip, max_duration)

Example:

from instagrapi.types import StoryMention, StoryMedia, StoryLink
from instagrapi.story import StoryBuilder

media_pk = cl.media_pk_from_url('https://www.instagram.com/p/CGgDsi7JQdS/')
media_path = cl.video_download(media_pk)
example = cl.user_info_by_username('example')

buildout = StoryBuilder(
    media_path,
    'Credits @example',
    [StoryMention(user=example)],
    Path('/path/to/background_720x1280.jpg')
).video(15)  # seconds

cl.video_upload_to_story(
    buildout.path,
    "Credits @example",
    mentions=buildout.mentions,
    links=[StoryLink(webUri='https://github.com/subzeroid/instagrapi')],
    medias=[StoryMedia(media_pk=media_pk)]
)

Result:

Photo upload:

cl.photo_upload_to_story('/app/image.jpg')

Upload photo as video:

buildout = StoryBuilder('/app/image.jpg').photo()
cl.video_upload_to_story(buildout.path)

Like & unlike story:

pk = cl.story_pk_from_url("https://instagram.com/stories/purely.anand/2884886531427631361/")
info = cl.story_info(pk).dict()

cl.story_like(info['id']) # To like story
cl.story_unlike(info['id']) # To unlike story

# another way to unlike story
cl.story_like(info['id'], revert=True)

More stories here https://www.instagram.com/wrclive/