instagram-mcp-server 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 official-Arvind
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include instagram_mcp_server *.py
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: instagram-mcp-server
3
+ Version: 1.0.0
4
+ Summary: MCP Server for full Instagram account control via AI agents — 68+ tools built with FastMCP + instagrapi
5
+ Author-email: official-Arvind <stararvindgaming@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/official-Arvind/instagram-mcp
8
+ Project-URL: Repository, https://github.com/official-Arvind/instagram-mcp
9
+ Project-URL: Issues, https://github.com/official-Arvind/instagram-mcp/issues
10
+ Keywords: instagram,mcp,model-context-protocol,ai,automation,fastmcp,instagrapi,claude,cursor,social-media
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Classifier: Topic :: Internet :: WWW/HTTP
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: fastmcp>=3.0.0
22
+ Requires-Dist: instagrapi>=2.1.0
23
+ Requires-Dist: pillow>=10.0.0
24
+ Requires-Dist: requests>=2.31.0
25
+ Dynamic: license-file
26
+
27
+ # 🤖 Instagram Control MCP Server
28
+
29
+ > **Let any AI agent fully control a real Instagram account — post, DM, follow, comment, search, and more.**
30
+
31
+ Built with **Python**, **[instagrapi](https://github.com/adw0rd/instagrapi)** (private mobile API), and **[FastMCP](https://github.com/jlowin/fastmcp)**.
32
+
33
+ ---
34
+
35
+ ## ✨ Features — 50+ Tools
36
+
37
+ ### 🔐 Authentication
38
+ | Tool | Description |
39
+ |------|-------------|
40
+ | `instagram_login_with_sessionid` | Login via browser cookie (recommended) |
41
+ | `instagram_login_with_credentials` | Login via username + password |
42
+ | `instagram_complete_2fa` | Submit 2FA authenticator code |
43
+ | `instagram_complete_challenge` | Submit email/SMS challenge code |
44
+ | `instagram_get_login_status` | Check active session |
45
+ | `instagram_logout` | Logout and clear session |
46
+
47
+ ### 👤 Profile
48
+ | Tool | Description |
49
+ |------|-------------|
50
+ | `instagram_get_profile` | Get profile info (any user) |
51
+ | `instagram_edit_profile` | Edit bio, name, website |
52
+ | `instagram_change_profile_picture` | Change profile picture |
53
+
54
+ ### 📸 Feed Posting
55
+ | Tool | Description |
56
+ |------|-------------|
57
+ | `instagram_post_photo` | Post a photo with caption + location |
58
+ | `instagram_post_album` | Post carousel (up to 10 items) |
59
+ | `instagram_post_video` | Post a feed video |
60
+ | `instagram_post_reel` | Post a Reel |
61
+ | `instagram_delete_post` | Delete a post permanently |
62
+ | `instagram_get_user_feed` | Get posts from any user |
63
+ | `instagram_get_timeline_feed` | Get your home feed |
64
+ | `instagram_get_media_info` | Get details of any post |
65
+ | `instagram_download_post` | Download photo/video to disk |
66
+
67
+ ### 📖 Stories
68
+ | Tool | Description |
69
+ |------|-------------|
70
+ | `instagram_post_photo_story` | Post a photo story |
71
+ | `instagram_post_video_story` | Post a video story |
72
+ | `instagram_get_user_stories` | Get active stories (any user) |
73
+ | `instagram_delete_story` | Delete your story |
74
+ | `instagram_get_story_viewers` | See who viewed your story |
75
+
76
+ ### 🌟 Highlights
77
+ | Tool | Description |
78
+ |------|-------------|
79
+ | `instagram_get_highlights` | Get highlights of any account |
80
+ | `instagram_create_highlight` | Create a new highlight |
81
+ | `instagram_delete_highlight` | Delete a highlight |
82
+
83
+ ### ❤️ Engagement
84
+ | Tool | Description |
85
+ |------|-------------|
86
+ | `instagram_like_post` | Like a post |
87
+ | `instagram_unlike_post` | Unlike a post |
88
+ | `instagram_save_post` | Save a post |
89
+ | `instagram_unsave_post` | Unsave a post |
90
+ | `instagram_get_post_likers` | See who liked a post |
91
+ | `instagram_comment_on_post` | Post a comment |
92
+ | `instagram_reply_to_comment` | Reply to a comment |
93
+ | `instagram_delete_comment` | Delete a comment |
94
+ | `instagram_like_comment` | Like a comment |
95
+ | `instagram_get_post_comments` | Get all comments on a post |
96
+
97
+ ### 👥 Following & Relations
98
+ | Tool | Description |
99
+ |------|-------------|
100
+ | `instagram_follow_user` | Follow a user |
101
+ | `instagram_unfollow_user` | Unfollow a user |
102
+ | `instagram_get_followers` | Get followers list |
103
+ | `instagram_get_following` | Get following list |
104
+ | `instagram_block_user` | Block a user |
105
+ | `instagram_unblock_user` | Unblock a user |
106
+ | `instagram_get_blocked_users` | See blocked accounts |
107
+
108
+ ### 💬 Direct Messages
109
+ | Tool | Description |
110
+ |------|-------------|
111
+ | `instagram_get_direct_threads` | Get DM thread list |
112
+ | `instagram_get_direct_messages` | Get messages in a thread |
113
+ | `instagram_send_direct_message` | Send text DM |
114
+ | `instagram_send_dm_photo` | Send photo DM |
115
+ | `instagram_send_dm_video` | Send video DM |
116
+ | `instagram_mark_thread_seen` | Mark thread as read |
117
+
118
+ ### 🔍 Search & Explore
119
+ | Tool | Description |
120
+ |------|-------------|
121
+ | `instagram_search_users` | Search users by name/username |
122
+ | `instagram_search_hashtag` | Get recent posts by hashtag |
123
+ | `instagram_get_hashtag_top_posts` | Get top posts by hashtag |
124
+ | `instagram_get_hashtag_info` | Get hashtag stats |
125
+ | `instagram_get_similar_accounts` | Find similar accounts |
126
+ | `instagram_get_location_posts` | Get posts from a location |
127
+
128
+ ### 🔔 Notifications & Activity
129
+ | Tool | Description |
130
+ |------|-------------|
131
+ | `instagram_get_notifications` | Get likes, comments, follows, mentions |
132
+ | `instagram_get_pending_follow_requests` | Get pending follow requests |
133
+
134
+ ---
135
+
136
+ ## 🚀 Installation
137
+
138
+ ### 1. Clone this repository
139
+ ```bash
140
+ git clone https://github.com/YOUR_USERNAME/instagram-mcp.git
141
+ cd instagram-mcp
142
+ ```
143
+
144
+ ### 2. Create virtual environment & install dependencies
145
+ ```bash
146
+ python -m venv venv
147
+
148
+ # Windows
149
+ venv\Scripts\pip install -r requirements.txt
150
+
151
+ # Mac/Linux
152
+ venv/bin/pip install -r requirements.txt
153
+ ```
154
+
155
+ ---
156
+
157
+ ## ⚙️ Integration with AI Clients
158
+
159
+ ### Claude Desktop
160
+ Edit `%APPDATA%\Claude\claude_desktop_config.json`:
161
+ ```json
162
+ {
163
+ "mcpServers": {
164
+ "instagram-control": {
165
+ "command": "C:\\path\\to\\instagram-mcp\\venv\\Scripts\\python.exe",
166
+ "args": ["C:\\path\\to\\instagram-mcp\\mcp_server.py"]
167
+ }
168
+ }
169
+ }
170
+ ```
171
+ Restart Claude Desktop. The Instagram tools will appear automatically.
172
+
173
+ ### Cursor IDE
174
+ 1. Open **Settings** → **Features** → **MCP**
175
+ 2. Click **+ Add New MCP Server**
176
+ 3. Set:
177
+ - **Name:** `instagram-control`
178
+ - **Type:** `command`
179
+ - **Command:** `C:\path\to\instagram-mcp\venv\Scripts\python.exe C:\path\to\instagram-mcp\mcp_server.py`
180
+
181
+ ---
182
+
183
+ ## 🔐 Logging In
184
+
185
+ ### Method 1: Session ID (Recommended — No 2FA, Most Stable)
186
+ 1. Log in to Instagram in your browser (Chrome/Firefox/Edge)
187
+ 2. Open **DevTools** (F12) → **Application** (Chrome) or **Storage** (Firefox)
188
+ 3. Navigate to **Cookies** → `https://www.instagram.com`
189
+ 4. Find and copy the value of the `sessionid` cookie
190
+ 5. Tell your AI agent:
191
+ > `instagram_login_with_sessionid(username="your_username", session_id="YOUR_COOKIE_VALUE")`
192
+
193
+ ### Method 2: Username & Password
194
+ ```
195
+ instagram_login_with_credentials(username="your_username", password="your_password")
196
+ ```
197
+ - If 2FA is required: call `instagram_complete_2fa(code="123456")`
198
+ - If a challenge triggers: call `instagram_complete_challenge(code="123456")`
199
+
200
+ ### Session Persistence
201
+ After the first successful login, a `instagram_session.json` file is saved locally.
202
+ On the next server start, the session is **automatically restored** — no re-authentication needed.
203
+
204
+ ---
205
+
206
+ ## ⚠️ Disclaimer
207
+ This project uses Instagram's unofficial private API (`instagrapi`). Usage violates Instagram's Terms of Service. Use responsibly — do not spam, harass, or automate high-frequency actions. The authors are not responsible for any account suspension or ban resulting from use of this software.
208
+
209
+ ---
210
+
211
+ ## 🛠️ Tech Stack
212
+ - **[FastMCP](https://github.com/jlowin/fastmcp)** — MCP server framework
213
+ - **[instagrapi](https://github.com/adw0rd/instagrapi)** — Instagram private API wrapper
214
+ - **[Pillow](https://pillow.readthedocs.io/)** — Image processing
215
+ - **[Requests](https://requests.readthedocs.io/)** — HTTP downloads
216
+
217
+ ---
218
+
219
+ ## 📄 License
220
+ MIT License — free to use, modify, and distribute.
@@ -0,0 +1,194 @@
1
+ # 🤖 Instagram Control MCP Server
2
+
3
+ > **Let any AI agent fully control a real Instagram account — post, DM, follow, comment, search, and more.**
4
+
5
+ Built with **Python**, **[instagrapi](https://github.com/adw0rd/instagrapi)** (private mobile API), and **[FastMCP](https://github.com/jlowin/fastmcp)**.
6
+
7
+ ---
8
+
9
+ ## ✨ Features — 50+ Tools
10
+
11
+ ### 🔐 Authentication
12
+ | Tool | Description |
13
+ |------|-------------|
14
+ | `instagram_login_with_sessionid` | Login via browser cookie (recommended) |
15
+ | `instagram_login_with_credentials` | Login via username + password |
16
+ | `instagram_complete_2fa` | Submit 2FA authenticator code |
17
+ | `instagram_complete_challenge` | Submit email/SMS challenge code |
18
+ | `instagram_get_login_status` | Check active session |
19
+ | `instagram_logout` | Logout and clear session |
20
+
21
+ ### 👤 Profile
22
+ | Tool | Description |
23
+ |------|-------------|
24
+ | `instagram_get_profile` | Get profile info (any user) |
25
+ | `instagram_edit_profile` | Edit bio, name, website |
26
+ | `instagram_change_profile_picture` | Change profile picture |
27
+
28
+ ### 📸 Feed Posting
29
+ | Tool | Description |
30
+ |------|-------------|
31
+ | `instagram_post_photo` | Post a photo with caption + location |
32
+ | `instagram_post_album` | Post carousel (up to 10 items) |
33
+ | `instagram_post_video` | Post a feed video |
34
+ | `instagram_post_reel` | Post a Reel |
35
+ | `instagram_delete_post` | Delete a post permanently |
36
+ | `instagram_get_user_feed` | Get posts from any user |
37
+ | `instagram_get_timeline_feed` | Get your home feed |
38
+ | `instagram_get_media_info` | Get details of any post |
39
+ | `instagram_download_post` | Download photo/video to disk |
40
+
41
+ ### 📖 Stories
42
+ | Tool | Description |
43
+ |------|-------------|
44
+ | `instagram_post_photo_story` | Post a photo story |
45
+ | `instagram_post_video_story` | Post a video story |
46
+ | `instagram_get_user_stories` | Get active stories (any user) |
47
+ | `instagram_delete_story` | Delete your story |
48
+ | `instagram_get_story_viewers` | See who viewed your story |
49
+
50
+ ### 🌟 Highlights
51
+ | Tool | Description |
52
+ |------|-------------|
53
+ | `instagram_get_highlights` | Get highlights of any account |
54
+ | `instagram_create_highlight` | Create a new highlight |
55
+ | `instagram_delete_highlight` | Delete a highlight |
56
+
57
+ ### ❤️ Engagement
58
+ | Tool | Description |
59
+ |------|-------------|
60
+ | `instagram_like_post` | Like a post |
61
+ | `instagram_unlike_post` | Unlike a post |
62
+ | `instagram_save_post` | Save a post |
63
+ | `instagram_unsave_post` | Unsave a post |
64
+ | `instagram_get_post_likers` | See who liked a post |
65
+ | `instagram_comment_on_post` | Post a comment |
66
+ | `instagram_reply_to_comment` | Reply to a comment |
67
+ | `instagram_delete_comment` | Delete a comment |
68
+ | `instagram_like_comment` | Like a comment |
69
+ | `instagram_get_post_comments` | Get all comments on a post |
70
+
71
+ ### 👥 Following & Relations
72
+ | Tool | Description |
73
+ |------|-------------|
74
+ | `instagram_follow_user` | Follow a user |
75
+ | `instagram_unfollow_user` | Unfollow a user |
76
+ | `instagram_get_followers` | Get followers list |
77
+ | `instagram_get_following` | Get following list |
78
+ | `instagram_block_user` | Block a user |
79
+ | `instagram_unblock_user` | Unblock a user |
80
+ | `instagram_get_blocked_users` | See blocked accounts |
81
+
82
+ ### 💬 Direct Messages
83
+ | Tool | Description |
84
+ |------|-------------|
85
+ | `instagram_get_direct_threads` | Get DM thread list |
86
+ | `instagram_get_direct_messages` | Get messages in a thread |
87
+ | `instagram_send_direct_message` | Send text DM |
88
+ | `instagram_send_dm_photo` | Send photo DM |
89
+ | `instagram_send_dm_video` | Send video DM |
90
+ | `instagram_mark_thread_seen` | Mark thread as read |
91
+
92
+ ### 🔍 Search & Explore
93
+ | Tool | Description |
94
+ |------|-------------|
95
+ | `instagram_search_users` | Search users by name/username |
96
+ | `instagram_search_hashtag` | Get recent posts by hashtag |
97
+ | `instagram_get_hashtag_top_posts` | Get top posts by hashtag |
98
+ | `instagram_get_hashtag_info` | Get hashtag stats |
99
+ | `instagram_get_similar_accounts` | Find similar accounts |
100
+ | `instagram_get_location_posts` | Get posts from a location |
101
+
102
+ ### 🔔 Notifications & Activity
103
+ | Tool | Description |
104
+ |------|-------------|
105
+ | `instagram_get_notifications` | Get likes, comments, follows, mentions |
106
+ | `instagram_get_pending_follow_requests` | Get pending follow requests |
107
+
108
+ ---
109
+
110
+ ## 🚀 Installation
111
+
112
+ ### 1. Clone this repository
113
+ ```bash
114
+ git clone https://github.com/YOUR_USERNAME/instagram-mcp.git
115
+ cd instagram-mcp
116
+ ```
117
+
118
+ ### 2. Create virtual environment & install dependencies
119
+ ```bash
120
+ python -m venv venv
121
+
122
+ # Windows
123
+ venv\Scripts\pip install -r requirements.txt
124
+
125
+ # Mac/Linux
126
+ venv/bin/pip install -r requirements.txt
127
+ ```
128
+
129
+ ---
130
+
131
+ ## ⚙️ Integration with AI Clients
132
+
133
+ ### Claude Desktop
134
+ Edit `%APPDATA%\Claude\claude_desktop_config.json`:
135
+ ```json
136
+ {
137
+ "mcpServers": {
138
+ "instagram-control": {
139
+ "command": "C:\\path\\to\\instagram-mcp\\venv\\Scripts\\python.exe",
140
+ "args": ["C:\\path\\to\\instagram-mcp\\mcp_server.py"]
141
+ }
142
+ }
143
+ }
144
+ ```
145
+ Restart Claude Desktop. The Instagram tools will appear automatically.
146
+
147
+ ### Cursor IDE
148
+ 1. Open **Settings** → **Features** → **MCP**
149
+ 2. Click **+ Add New MCP Server**
150
+ 3. Set:
151
+ - **Name:** `instagram-control`
152
+ - **Type:** `command`
153
+ - **Command:** `C:\path\to\instagram-mcp\venv\Scripts\python.exe C:\path\to\instagram-mcp\mcp_server.py`
154
+
155
+ ---
156
+
157
+ ## 🔐 Logging In
158
+
159
+ ### Method 1: Session ID (Recommended — No 2FA, Most Stable)
160
+ 1. Log in to Instagram in your browser (Chrome/Firefox/Edge)
161
+ 2. Open **DevTools** (F12) → **Application** (Chrome) or **Storage** (Firefox)
162
+ 3. Navigate to **Cookies** → `https://www.instagram.com`
163
+ 4. Find and copy the value of the `sessionid` cookie
164
+ 5. Tell your AI agent:
165
+ > `instagram_login_with_sessionid(username="your_username", session_id="YOUR_COOKIE_VALUE")`
166
+
167
+ ### Method 2: Username & Password
168
+ ```
169
+ instagram_login_with_credentials(username="your_username", password="your_password")
170
+ ```
171
+ - If 2FA is required: call `instagram_complete_2fa(code="123456")`
172
+ - If a challenge triggers: call `instagram_complete_challenge(code="123456")`
173
+
174
+ ### Session Persistence
175
+ After the first successful login, a `instagram_session.json` file is saved locally.
176
+ On the next server start, the session is **automatically restored** — no re-authentication needed.
177
+
178
+ ---
179
+
180
+ ## ⚠️ Disclaimer
181
+ This project uses Instagram's unofficial private API (`instagrapi`). Usage violates Instagram's Terms of Service. Use responsibly — do not spam, harass, or automate high-frequency actions. The authors are not responsible for any account suspension or ban resulting from use of this software.
182
+
183
+ ---
184
+
185
+ ## 🛠️ Tech Stack
186
+ - **[FastMCP](https://github.com/jlowin/fastmcp)** — MCP server framework
187
+ - **[instagrapi](https://github.com/adw0rd/instagrapi)** — Instagram private API wrapper
188
+ - **[Pillow](https://pillow.readthedocs.io/)** — Image processing
189
+ - **[Requests](https://requests.readthedocs.io/)** — HTTP downloads
190
+
191
+ ---
192
+
193
+ ## 📄 License
194
+ MIT License — free to use, modify, and distribute.
@@ -0,0 +1,9 @@
1
+ """
2
+ instagram_mcp_server — Instagram Control MCP Server
3
+ A FastMCP + instagrapi powered server exposing 68+ tools for full
4
+ Instagram account control via any MCP-compatible AI agent.
5
+ """
6
+
7
+ __version__ = "1.0.0"
8
+ __author__ = "official-Arvind"
9
+ __email__ = "stararvindgaming@gmail.com"
@@ -0,0 +1,20 @@
1
+ """
2
+ Entry point for running the Instagram MCP server as a CLI command.
3
+ Usage: instagram-mcp
4
+ """
5
+ import os
6
+ import sys
7
+
8
+
9
+ def main():
10
+ # Ensure the package directory is in sys.path when called as CLI
11
+ pkg_dir = os.path.dirname(os.path.abspath(__file__))
12
+ if pkg_dir not in sys.path:
13
+ sys.path.insert(0, pkg_dir)
14
+
15
+ from instagram_mcp_server.mcp_server import mcp
16
+ mcp.run()
17
+
18
+
19
+ if __name__ == "__main__":
20
+ main()
@@ -0,0 +1,183 @@
1
+ """
2
+ instagram_client.py
3
+ --------------------
4
+ Core Instagram client wrapper built on top of instagrapi.
5
+ Handles authentication, session persistence, 2FA/challenge flows,
6
+ and exposes a clean API for mcp_server.py to consume.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import logging
12
+ from typing import Optional, Dict, Any
13
+
14
+ from instagrapi import Client
15
+ from instagrapi.exceptions import (
16
+ TwoFactorRequired,
17
+ ChallengeRequired,
18
+ LoginRequired,
19
+ UserNotFound,
20
+ MediaNotFound,
21
+ RateLimitError,
22
+ BadPassword,
23
+ )
24
+
25
+ # Log to stderr only — never stdout (would corrupt stdio MCP transport)
26
+ logging.basicConfig(stream=sys.stderr, level=logging.INFO,
27
+ format="[instagram_client] %(levelname)s: %(message)s")
28
+ logger = logging.getLogger("instagram_client")
29
+
30
+
31
+ class InstagramClientWrapper:
32
+ def __init__(self, session_path: str = "instagram_session.json"):
33
+ self.cl = Client()
34
+ self.cl.delay_range = [1, 3] # human-like delays between requests
35
+ self.session_path = session_path
36
+ self.username: Optional[str] = None
37
+ self.password: Optional[str] = None
38
+ self.pending_2fa: bool = False
39
+ self.pending_challenge: bool = False
40
+
41
+ # ------------------------------------------------------------------
42
+ # SESSION MANAGEMENT
43
+ # ------------------------------------------------------------------
44
+
45
+ def load_session(self) -> bool:
46
+ """Attempts to load a saved session from disk."""
47
+ if os.path.exists(self.session_path):
48
+ try:
49
+ logger.info(f"Loading session from {self.session_path}")
50
+ self.cl.load_settings(self.session_path)
51
+ return True
52
+ except Exception as e:
53
+ logger.error(f"Failed to load session: {e}")
54
+ try:
55
+ os.remove(self.session_path)
56
+ except Exception:
57
+ pass
58
+ return False
59
+
60
+ def save_session(self):
61
+ """Saves the current session to disk."""
62
+ try:
63
+ self.cl.dump_settings(self.session_path)
64
+ logger.info(f"Session saved to {self.session_path}")
65
+ except Exception as e:
66
+ logger.error(f"Failed to save session: {e}")
67
+
68
+ def is_logged_in(self) -> bool:
69
+ """Probes Instagram to verify the current session is valid."""
70
+ try:
71
+ if self.cl.user_id:
72
+ self.cl.get_timeline_feed()
73
+ return True
74
+ except Exception:
75
+ pass
76
+ return False
77
+
78
+ def init_from_saved_session(self) -> Dict[str, Any]:
79
+ """Try restoring an existing session on startup."""
80
+ if self.load_session():
81
+ if self.is_logged_in():
82
+ self.username = self.cl.username
83
+ return {"status": "success", "message": f"Auto-restored session for @{self.username}"}
84
+ return {"status": "not_logged_in", "message": "No valid saved session found."}
85
+
86
+ # ------------------------------------------------------------------
87
+ # LOGIN METHODS
88
+ # ------------------------------------------------------------------
89
+
90
+ def login_with_credentials(self, username: str, password: str,
91
+ verification_code: Optional[str] = None) -> Dict[str, Any]:
92
+ """Login using username + password, with optional 2FA code."""
93
+ self.username = username
94
+ self.password = password
95
+ self.pending_2fa = False
96
+ self.pending_challenge = False
97
+
98
+ def challenge_code_handler(uname, choice):
99
+ logger.warning(f"Challenge triggered for {uname} via {choice}")
100
+ self.pending_challenge = True
101
+ raise ChallengeRequired("Challenge code required.")
102
+
103
+ self.cl.challenge_code_handler = challenge_code_handler
104
+
105
+ try:
106
+ logger.info(f"Logging in as {username}...")
107
+ if verification_code:
108
+ self.cl.login(username, password, verification_code=verification_code)
109
+ else:
110
+ self.cl.login(username, password)
111
+
112
+ self.save_session()
113
+ return {"status": "success", "message": f"Logged in as @{username}"}
114
+
115
+ except TwoFactorRequired:
116
+ self.pending_2fa = True
117
+ return {
118
+ "status": "needs_2fa",
119
+ "message": "2FA required. Call instagram_complete_2fa with the code from your authenticator app."
120
+ }
121
+ except ChallengeRequired:
122
+ self.pending_challenge = True
123
+ return {
124
+ "status": "needs_challenge",
125
+ "message": "Security challenge triggered. Call instagram_complete_challenge with the code sent to your email/SMS."
126
+ }
127
+ except BadPassword:
128
+ return {"status": "error", "message": "Incorrect password."}
129
+ except Exception as e:
130
+ logger.error(f"Login error: {e}")
131
+ return {"status": "error", "message": str(e)}
132
+
133
+ def login_with_sessionid(self, username: str, session_id: str) -> Dict[str, Any]:
134
+ """Login using a browser sessionid cookie — most stable method."""
135
+ self.username = username
136
+ self.pending_2fa = False
137
+ self.pending_challenge = False
138
+
139
+ try:
140
+ logger.info(f"Logging in via session ID for @{username}...")
141
+ self.cl.login_by_sessionid(session_id)
142
+
143
+ if self.is_logged_in():
144
+ self.username = self.cl.username
145
+ self.save_session()
146
+ return {"status": "success", "message": f"Authenticated as @{self.username} via session ID."}
147
+ else:
148
+ return {"status": "error", "message": "Session ID login verification failed. The session may be expired."}
149
+ except Exception as e:
150
+ logger.error(f"Session ID login error: {e}")
151
+ return {"status": "error", "message": str(e)}
152
+
153
+ def complete_2fa(self, code: str) -> Dict[str, Any]:
154
+ """Completes a pending 2FA login."""
155
+ if not self.username or not self.password:
156
+ return {"status": "error", "message": "No pending login. Call login_with_credentials first."}
157
+ return self.login_with_credentials(self.username, self.password, verification_code=code)
158
+
159
+ def complete_challenge(self, code: str) -> Dict[str, Any]:
160
+ """Completes a pending security challenge."""
161
+ if not self.username or not self.password:
162
+ return {"status": "error", "message": "No pending login. Call login_with_credentials first."}
163
+ return self.login_with_credentials(self.username, self.password, verification_code=code)
164
+
165
+ def logout(self) -> Dict[str, Any]:
166
+ """Logs out and removes saved session."""
167
+ try:
168
+ self.cl.logout()
169
+ if os.path.exists(self.session_path):
170
+ os.remove(self.session_path)
171
+ self.username = None
172
+ self.password = None
173
+ return {"status": "success", "message": "Logged out and session cleared."}
174
+ except Exception as e:
175
+ return {"status": "error", "message": str(e)}
176
+
177
+ def get_login_status(self) -> Dict[str, Any]:
178
+ logged = self.is_logged_in()
179
+ return {
180
+ "logged_in": logged,
181
+ "username": (self.cl.username if logged else None),
182
+ "user_id": (str(self.cl.user_id) if logged else None)
183
+ }