subzeroid / instagrapi

🔥 The fastest and powerful Python library for Instagram Private API 2024
https://hikerapi.com/p/bkXQlaVe
MIT License
4.19k stars 665 forks source link

[BUG] photo_upload and photo_upload_to_story fails when logged in via sessionid #1982

Open jephjohnson opened 1 month ago

jephjohnson commented 1 month ago

Try Instagrapi SaaS with a free trial https://hikerapi.com/p/5GBWznd3

Describe the bug When logging in via a sessionid and calling the photo_upload or the photo_upload_to_story function the post results in a POST /post HTTP/1.1" 500

To Reproduce Login using a sessionid and call the photo_upload or upload_to_story method

client = Client()
sessionid = "xxxx"
 try:
        result = client.login_by_sessionid(sessionid)
    except (PrivateError, ValidationError) as e:
        print(f"An error occurred: {e}")

try:
        if upload_to_feed:
            media = cl.photo_upload(image_path, caption=content)
            if media:
                print("Photo uploaded to feed successfully!")
            else:
                print("Failed to upload photo to feed.")

        if upload_to_story:
            media = cl.photo_upload_to_story(image_path, caption=content)
            if media:
                print("Story shared successfully with location!")
            else:
                print("Failed to upload story to Instagram.")

        if upload_to_feed or upload_to_story:
            os.remove(image_path)
            print(f"Deleted image: {image_path}")

        return True
    except Exception as e:
        print(f"Upload failed: {e}")
        if "Please wait a few minutes before you try again" in str(e):
            print("Encountered rate limiting. Waiting for a minute before retrying...")
            time.sleep(60)  # Wait for a minute before retrying
        return False

will result in

Upload failed: login_required
100.0.0.1 - - [24/Jul/2024 20:37:45] "POST /post HTTP/1.1" 500 -

Traceback Show your full traceback so that it is clear where exactly the error occurred.

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Additional context Loggin in via username and passwords works great!

sujay1599 commented 1 month ago

Consider relogin to get a new cookie.

Make sure to keep uuiud same.

This is how I manage authentication: https://github.com/sujay1599/InstagramTheftyScraperPosterHuman/blob/main/auth.py

Hope that helps.

jephjohnson commented 1 month ago

Hmm, my situation be a bit unique since I am using the Instagram oauth flow to login. Not manually hardcoding the values…

sujay1599 commented 1 month ago

Hmm, my situation be a bit unique since I am using the Instagram oauth flow to login. Not manually hardcoding the values…

So not session?

Can u share ur method?

sujay1599 commented 1 month ago

Hmm, my situation be a bit unique since I am using the Instagram oauth flow to login. Not manually hardcoding the values…

Mine creates a session.json too.

And if same account logs it uses that session.

jephjohnson commented 1 month ago

Hey there, take the following. I think the issue also may be that I am not getting the sessionId properly. You will also need to create an app here and use your creds for the placeholders in the code - https://developers.facebook.com/apps/?show_reminder=true. Attached are the steps to get the instagram creds for the oauth flow to work -

Screenshot 2024-07-28 at 9 30 33 PM Screenshot 2024-07-28 at 9 30 46 PM

Py:

from flask import Flask, redirect, request, session, url_for, render_template_string
import requests
import os
from instagrapi import Client

app = Flask(__name__)
app.secret_key = os.urandom(24)

# Instagram OAuth settings
CLIENT_ID = ''
CLIENT_SECRET = ''
REDIRECT_URI = 'http://demo.com/callback'  # Make sure this matches your actual callback URL

# Step 1: Redirect to Instagram for authorization
@app.route('/login')
def login():
    instagram_auth_url = (
        'https://api.instagram.com/oauth/authorize'
        f'?client_id={CLIENT_ID}'
        f'&redirect_uri={REDIRECT_URI}'
        '&scope=user_profile,user_media'
        '&response_type=code'
    )
    return redirect(instagram_auth_url)

# Step 2: Handle callback from Instagram
@app.route('/callback')
def callback():
    code = request.args.get('code')
    if not code:
        return 'Authorization failed.'

    token_url = 'https://api.instagram.com/oauth/access_token'
    payload = {
        'client_id': CLIENT_ID,
        'client_secret': CLIENT_SECRET,
        'grant_type': 'authorization_code',
        'redirect_uri': REDIRECT_URI,
        'code': code,
    }

    response = requests.post(token_url, data=payload)
    if response.status_code != 200:
        return 'Failed to get access token.'

    access_token = response.json().get('access_token')
    print("Short-Lived Access Token:", access_token)  # Debugging

    # Exchange short-lived token for long-lived token
    long_lived_token_url = 'https://graph.instagram.com/access_token'
    long_lived_payload = {
        'grant_type': 'ig_exchange_token',
        'client_secret': CLIENT_SECRET,
        'access_token': access_token,
    }

    long_lived_response = requests.get(long_lived_token_url, params=long_lived_payload)
    if long_lived_response.status_code != 200:
        return f"Failed to exchange for long-lived token: {long_lived_response.json()}"

    long_lived_access_token = long_lived_response.json().get('access_token')
    print("Long-Lived Access Token:", long_lived_access_token)  # Debugging
    session['access_token'] = long_lived_access_token

    # Retrieve the session ID (this is a placeholder - replace with your method of obtaining the session ID)
    cl = Client()
    cl.login_by_access_token(long_lived_access_token)
    session_id = cl.sessionid
    session['session_id'] = session_id

    # JavaScript to close the pop-up and redirect the main window
    close_popup_script = '''
    <script type="text/javascript">
        window.opener.location.href = '/upload';
        window.close();
    </script>
    '''
    return close_popup_script

@app.route('/upload', methods=['GET'])
def upload():
    session_id = session.get('session_id')
    print("Session ID for Upload:", session_id)  # Debugging
    if not session_id:
        return redirect(url_for('login'))

    # Log in with instagrapi using the session ID
    cl = Client()
    cl.login_by_sessionid(session_id)

    # Upload a photo
    photo_path = 'path/to/your/photo.jpg'  # Change this to the path of the photo you want to upload
    caption = 'Your photo caption'
    cl.photo_upload(photo_path, caption)

    return 'Photo uploaded successfully!'

# Serve the main page with JavaScript to open the login in a pop-up window
@app.route('/')
def index():
    index_html = '''
    <!DOCTYPE html>
    <html>
    <head>
        <title>Instagram OAuth</title>
        <script type="text/javascript">
            function openPopup() {
                var width = 600;
                var height = 600;
                var left = (screen.width - width) / 2;
                var top = (screen.height - height) / 2;
                var url = "{{ url_for('login') }}";
                var options = "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=" + width + ",height=" + height + ",top=" + top + ",left=" + left;
                window.open(url, "Instagram Login", options);
            }
        </script>
    </head>
    <body>
        <h1>Welcome to Instagram OAuth</h1>
        <button onclick="openPopup()">Login with Instagram</button>
    </body>
    </html>
    '''
    return render_template_string(index_html)

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(debug=True, host='0.0.0.0', port=port)