✨🐥 InstaTweet 🐤✨
Automatically Repost Content From Instagram to Twitter
Ever tried sharing an Instagram post to Twitter, only to find out that all you tweeted was a link, and not the actual photo/video?

Humiliating 🤮
That could be literally anything. Nobody will click it.
InstaTweet
shares the actual content of the post. Not just a link to it.

With InstaTweet
, you can rest easy knowing that,
although nobody will click the link, they’ll at least see what you posted.
What’s InstaTweet?
InstaTweet
is a customizable tool to automatically repost content from Instagram to Twitter.
Simply create a Profile
,
configure the Mandatory Settings,
and add_users()
to repost from
from InstaTweet import Profile
# Create a new (local) Profile
>>> profile = Profile('myProfile')
# Configure the required settings (at minimum)
>>> profile.twitter_keys = twitter_api_keys
>>> profile.session_id = '6011991A'
# Add at least one Instagram account to repost from
>>> profile.add_users('the.dailykitten')
Once configured, the Profile
can be used to initialize and
start()
an InstaTweet
object
from InstaTweet import InstaTweet
# Directly initialize with the Profile from above
>>> insta_tweet = InstaTweet(profile)
# Or, save the Profile...
>>> profile.save()
Saved Local Profile myProfile
# ...then InstaTweet.load() the settings in (by Profile name)
>>> insta_tweet = InstaTweet.load(profile_name="myProfile")
# Run InstaTweet by calling start()
>>> insta_tweet.start()
From the Docs…
- InstaTweet.start()[source]View on GitHub
InstaTweets all users that have been added to the loaded
Profile
Each user’s IG page will be scraped and compared to the
scraped
list in theirUSER_MAPPING
. Posts that weren’t previously scraped will be downloaded and tweetedNote
If
InstaTweet
fails todownload_post()
orsend_tweet()
, theUSER_MAPPING
won’t be updatedThis ensures that failed repost attempts are retried in the next call to
start()
If a save file for the Profile already
exists
, successful reposts will trigger a call tosave()
As InstaTweet
runs, its progress will be logged to console:
Starting InstaTweet for Profile: myProfile
Checking posts from @the.dailykitten
...
Finished insta-tweeting for @the.dailykitten
All users have been insta-tweeted
Okay… But Why? 😟
But Why? 🤨
InstaTweet has two main use cases:
To automatically share your own Instagram posts to Twitter
To automatically tweet new content from other Instagram users
Regardless of your intention, InstaTweet will detect new posts from the users you specify, download them, and repost them to Twitter.
Documentation
The rest of this README, the API documentation, and snippets can all be found on Read the Docs
I put a lot of time into creating the documentation for this package, it was a struggle, so it’d mean a lot to me if you could please continue reading there! 🥰
Installation
To install using pip:
pip install insta-tweet
Please note that InstaTweet
requires Python >= 3.8
✨🐥 InstaTweet 🐤✨
Automatically Repost Content From Instagram to Twitter
Ever tried sharing an Instagram post to Twitter, only to find out that all you tweeted was a link, and not the actual photo/video?

Humiliating 🤮
That could be literally anything. Nobody will click it.
InstaTweet
shares the actual content of the post. Not just a link to it.

With InstaTweet
, you can rest easy knowing that,
although nobody will click the link, they’ll at least see what you posted.
What’s InstaTweet?
InstaTweet
is a customizable tool to automatically repost content from Instagram to Twitter.
Simply create a Profile
,
configure the Mandatory Settings,
and add_users()
to repost from
from InstaTweet import Profile
# Create a new (local) Profile
>>> profile = Profile('myProfile')
# Configure the required settings (at minimum)
>>> profile.twitter_keys = twitter_api_keys
>>> profile.session_id = '6011991A'
# Add at least one Instagram account to repost from
>>> profile.add_users('the.dailykitten')
Once configured, the Profile
can be used to initialize and
start()
an InstaTweet
object
from InstaTweet import InstaTweet
# Directly initialize with the Profile from above
>>> insta_tweet = InstaTweet(profile)
# Or, save the Profile...
>>> profile.save()
Saved Local Profile myProfile
# ...then InstaTweet.load() the settings in (by Profile name)
>>> insta_tweet = InstaTweet.load(profile_name="myProfile")
# Run InstaTweet by calling start()
>>> insta_tweet.start()
From the Docs…
- InstaTweet.start()[source]View on GitHub
InstaTweets all users that have been added to the loaded
Profile
Each user’s IG page will be scraped and compared to the
scraped
list in theirUSER_MAPPING
. Posts that weren’t previously scraped will be downloaded and tweetedNote
If
InstaTweet
fails todownload_post()
orsend_tweet()
, theUSER_MAPPING
won’t be updatedThis ensures that failed repost attempts are retried in the next call to
start()
If a save file for the Profile already
exists
, successful reposts will trigger a call tosave()
As InstaTweet
runs, its progress will be logged to console:
Starting InstaTweet for Profile: myProfile
Checking posts from @the.dailykitten
...
Finished insta-tweeting for @the.dailykitten
All users have been insta-tweeted
Okay… But Why? 😟
But Why? 🤨
InstaTweet has two main use cases:
To automatically share your own Instagram posts to Twitter
To automatically tweet new content from other Instagram users
Regardless of your intention, InstaTweet will detect new posts from the users you specify, download them, and repost them to Twitter.
Documentation
The rest of this README, the API documentation, and snippets can all be found on Read the Docs
I put a lot of time into creating the documentation for this package, it was a struggle, so it’d mean a lot to me if you could please continue reading there! 🥰
Installation
To install using pip:
pip install insta-tweet
Please note that InstaTweet
requires Python >= 3.8
Getting Started
InstaTweet Profiles
InstaTweet uses the Profile
class to help manage Twitter accounts, Instagram sessions, and user maps.
- class InstaTweet.profile.Profile(name='default', local=True, **kwargs)[source]View on GitHub
The
Profile
is a configuration class used extensively throughout the packageIt consists of a
user_map
and an associated collection of API/web scraping settings…
About the User Map
The
user_map
is a dict containing info about the users added to aProfile
It’s used to help detect new posts and compose tweets on a per-user basis
Entries are created when you
add_users()
, which map the user to aUSER_MAPPING
The
USER_MAPPING
maintains lists of hashtags, scraped posts, and sent tweetsThe mapping is updated when you
add_hashtags()
and successfullysend_tweet()
You can access entries in the
user_map
as follows:get_user()
allows you to retrieve a full entry by usernameget_hashtags_for()
,get_scraped_from()
,get_tweets_for()
provide access to lists
…
[Optional]
A unique, identifying
name
can be assigned to the Profile, which may then be used tosave()
and, in turn,load()
its settingsThis makes it extremely easy to switch between Profiles and create templates
Saving isn’t a requirement to
start()
InstaTweet, but…To
get_new_posts()
, InstaTweet makes comparisons with thescraped
list in theuser_map
Saving this list ensures you don’t
send_tweet()
for a post more than once
…
Important
If you do
save()
your profile, the save location is determined by the value ofProfile.local
Local saves are made to the
LOCAL_DIR
, as pickle filesRemote saves are made to a database (via the
db
module) as pickle bytes
You MUST configure the
DATABASE_URL
environment variable to save/load remotelyInstaTweet uses
SQLAlchemy
to create aDBConnection
– any db it supports is compatibleSee the
db
module for more information
Profile Settings
All settings can be configured in two ways:
By passing them as keyword arguments when initializing a
Profile
By setting them directly as object attributes after the
Profile
object is created
Mandatory Settings
session_id
— Instagram sessionid cookie, obtained by logging in on a desktop browsertwitter_keys
— Twitter API keys with v1.1 endpoint access
Mandatory Settings with Default Values
Entirely Optional Settings
proxy_key
— Environment variable to retrieve proxies from when making requests to Instagram/Twitteruser_map
— Fully formatted dictionary of IG usernames mapped to theirUSER_MAPPING
Creating a Profile
from InstaTweet import Profile
# Initialize a profile with arguments
p = Profile(
name='myProfile',
session_id='6011991A'
)
# Initialize a profile with no arguments
q = Profile()
q.name = 'myProfile'
q.session_id = '6011991A'
All settings can be accessed via the config
dict.
If you just want to look, call view_config()
# View and compare configuration settings
>>> q.view_config()
>>> print(f'Same Config: {p.config==q.config}')
Output:
name : myProfile
local : True
session_id : 6011991A
twitter_keys : {'Consumer Key': 'string', 'Consumer Secret': 'string', 'Access Token': 'string', 'Token Secret': 'string'}
user_agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36
proxy_key : None
user_map : {}
Same Config: True
…
Validating Profile Settings
Property setters validate data types for the Mandatory Settings
Requirements aren’t strictly enforced until
start()
is called, which will firstvalidate()
the profile settings
Populating the User Map
The User Map
The user_map
allows a Profile
to maintain
a history of package-related activity for its added IG users
Users are mapped to their USER_MAPPING
, which contains their associated lists of:
USER_MAPPING = {'hashtags': [], 'scraped': [], 'tweets': []}
hashtags
— the user’s associated hashtag list (for use when composing tweets)scraped
— the list of posts that have been scraped from the user (only the post id)tweets
— the list of sent tweets containing media scraped from that user (limited data)
The mapping gets updated each time InstaTweet
successfully scrapes and tweets a post from the user
Adding Users
Use the add_users()
method to add one or more Instagram users
to a Profile
’s user_map
from InstaTweet import Profile
# Add one user at a time
>>> p = Profile('myProfile')
>>> p.add_users('the.dailykitten', send_tweet=True)
Added Instagram user @the.dailykitten to the user map
# Add multiple users at once
>>> usernames = ['dailykittenig','the.daily.kitten.ig']
>>> p.add_users(usernames)
Added Instagram user @dailykittenig to the user map
Added Instagram user @the.daily.kitten.ig to the user map
The get_user()
method can be used to retrieve the full USER_MAPPING
of an added user
>> p.get_user('the.dailykitten')
{'hashtags': [], 'scraped': [-1], 'tweets': []}
User Map Access Methods
User Map Access Methods
The Profile
has several methods that allow for easy access to the user_map
get_user()
provides access to a particular user’sUSER_MAPPING
get_scraped_from()
returns the list of posts scraped from a specified userget_hashtags_for()
returns the list of hashtags to use in tweets for the specified userget_tweets_for()
returns a list of tweets that use the specified user’s scraped content
All lists returned by these methods can be modified in place. For example:
# View the list of hashtags by username
>> print(p.get_hashtags_for('the.daily.kitten.ig'))
['kittygram', 'kittycat']
# Retrieve and modify the list
>> p.get_hashtags_for('the.daily.kitten.ig').append('kittypoop')
>> print(p.get_hashtags_for('the.daily.kitten.ig'))
['kittygram', 'kittycat', 'kittypoop']
Saving a Profile
Saving a Profile
When you save()
your Profile
, the current or specified name
will be used to create or update a save file in the location specified by local
From the Docs…
- Profile.save(name=None, alert=True)[source]View on GitHub
Pickles and saves the
Profile
using the specified or currently set name.
- InstaTweet.profile.Profile.local =True
Indicates if saves should be made locally (
True
) or on a remote database (False
)- Return type
Important!!
You MUST configure the DATABASE_URL
environment variable to save/load remotely
InstaTweet uses SQLAlchemy
to create a DBConnection
Any
SQLAlchemy
-supported database is therefore also supported byInstaTweet
See the
db
module for more information
Although you don’t need to save()
the Profile to start()
InstaTweet,
it’s highly suggested since:
It’s an easy way to group API settings together
It keeps track of previously scraped & tweeted posts, which is used to detect new posts
Example: Save a Profile
from InstaTweet import Profile
>>> p = Profile('myProfile')
>>> p.save()
Saved Local Profile myProfile
>>> q = Profile()
>>> q.save('aProfile')
Saved Local Profile aProfile
# Try to save under a name that's already used...
>>> q.save('myProfile')
FileExistsError: Local save file already exists for profile named "myProfile"
Please choose another name, load the profile, or delete the file.
>>> Profile.profile_exists("aProfile")
True
Schedule InstaTweet
You can easily schedule InstaTweet using the provided scheduler script
#scheduler.py
from InstaTweet import InstaTweet
PROFILES = ['aProfile', 'myProfile']
LOCAL = True
def run(profile_name: str, local: bool = LOCAL):
"""Loads and InstaTweets a profile
:param profile_name: the name of the :class:`~.Profile`
:param local: if the profile is saved locally or in a SQLAlchemy supported database
"""
insta_tweet = InstaTweet.load(profile_name, local=local)
insta_tweet.start()
if __name__ == '__main__':
for profile in PROFILES:
run(profile, local=LOCAL)
InstaTweet README
InstaTweet Package
Below, you’ll find the documentation for each class/module in the InstaTweet
package.
The InstaTweet
class
Not to be confused with the package, the InstaTweet
class is the main point of interaction for a user of
the package
It uses a fully configured
Profile
to initialize anInstaClient
andTweetClient
, which are used to scrape and tweet posts whenstart()
is called
…
- class InstaTweet.instatweet.InstaTweet(profile)[source]View on GitHub
Bases:
object
Uses the settings from a Profile to do the actual InstaTweeting
You might be wondering, what’s InstaTweeting? According to TDK Dictionary:
InstaTweet (verb):
To load a
Profile
🠖 scrapeposts
from its Instagram users 🠖download_post()
&send_tweet()
for any new content 🠖 update theuser_map
🠖save()
the profile if itexists
Example Sentence
Oh, you lost 700 Twitter followers after you shared your IG post? Well maybe if people actually saw the picture and not just the caption your tweet would’ve been less creepy. You should’ve InstaTweeted it.
- __init__(profile)[source]View on GitHub
Initializes
InstaTweet
using a fully configuredProfile
The
Profile
will be used to initialize anInstaClient
andTweetClient
Note
InstaTweet won’t
validate()
the Profile settings until you callstart()
- classmethod load(profile_name, local=True)[source]View on GitHub
Loads a profile by name
- Parameters
- Return type
- get_proxies()[source]View on GitHub
Retrieve proxies using the loaded Profile’s
proxy_key
- get_insta_client()[source]View on GitHub
Initializes an
InstaClient
using the loadedProfile
settings- Return type
- get_tweet_client()[source]View on GitHub
Initializes an
TweetClient
using the loadedProfile
settings- Return type
- start()[source]View on GitHub
InstaTweets all users that have been added to the loaded
Profile
Each user’s IG page will be scraped and compared to the
scraped
list in theirUSER_MAPPING
. Posts that weren’t previously scraped will be downloaded and tweetedNote
If
InstaTweet
fails todownload_post()
orsend_tweet()
, theUSER_MAPPING
won’t be updatedThis ensures that failed repost attempts are retried in the next call to
start()
If a save file for the Profile already
exists
, successful reposts will trigger a call tosave()
- get_new_posts(username)[source]View on GitHub
Scrapes recent posts from an Instagram user and returns all posts that haven’t been tweeted yet
NOTE: If a user’s
scraped
list is empty, no posts will be returned.- Instead, the user is “initialized” as follows:
Their
scraped
list will be populated with the ID’s from the most recent postsThese IDs are then used in future calls to the method to determine which posts to tweet
The Profile
class
- class InstaTweet.profile.Profile(name='default', local=True, **kwargs)[source]View on GitHub
Bases:
object
The
Profile
is a configuration class used extensively throughout the packageIt consists of a
user_map
and an associated collection of API/web scraping settings…
About the User Map
The
user_map
is a dict containing info about the users added to aProfile
It’s used to help detect new posts and compose tweets on a per-user basis
Entries are created when you
add_users()
, which map the user to aUSER_MAPPING
The
USER_MAPPING
maintains lists of hashtags, scraped posts, and sent tweetsThe mapping is updated when you
add_hashtags()
and successfullysend_tweet()
You can access entries in the
user_map
as follows:get_user()
allows you to retrieve a full entry by usernameget_hashtags_for()
,get_scraped_from()
,get_tweets_for()
provide access to lists
…
[Optional]
A unique, identifying
name
can be assigned to the Profile, which may then be used tosave()
and, in turn,load()
its settingsThis makes it extremely easy to switch between Profiles and create templates
Saving isn’t a requirement to
start()
InstaTweet, but…To
get_new_posts()
, InstaTweet makes comparisons with thescraped
list in theuser_map
Saving this list ensures you don’t
send_tweet()
for a post more than once
…
Important
If you do
save()
your profile, the save location is determined by the value ofProfile.local
Local saves are made to the
LOCAL_DIR
, as pickle filesRemote saves are made to a database (via the
db
module) as pickle bytes
You MUST configure the
DATABASE_URL
environment variable to save/load remotelyInstaTweet uses
SQLAlchemy
to create aDBConnection
– any db it supports is compatibleSee the
db
module for more information
- USER_MAPPING = {'hashtags': [], 'scraped': [], 'tweets': []}
Template for an entry in the
user_map
- LOCAL_DIR = '/home/docs/checkouts/readthedocs.org/user_builds/instatweet/checkouts/develop/docs/source/profiles'
Directory where local profiles are saved
- __init__(name='default', local=True, **kwargs)[source]View on GitHub
Create a new
Profile
Note
Profile
creation is mandatory to use theInstaTweet
packageRequired as a parameter to initialize an
InstaTweet
objectNaming and saving it is ideal, but not necessary to
start()
InstaTweet
- Parameters
- Keyword Arguments
- session_id (
str
) Instagram
sessionid
cookie, obtained by logging in through browser
- session_id (
- twitter_keys (
dict
) Twitter API Keys with v1.1 endpoint access (see
DEFAULT_KEYS
for a template)
- twitter_keys (
- user_agent (
str
) – Optional The user agent to use for requests; uses a currently working hardcoded agent if not provided
- user_agent (
- proxy_key (
str
) – Optional Environment variable to retrieve proxies from
- proxy_key (
- user_map
dict
: Mapping of added Instagram users and theirUSER_MAPPING
Profile Creation Tips
All attributes can be passed as arguments at initialization or set directly afterwards
Property setters validate data types for the Mandatory Settings
The
Profile
as a whole is validated byvalidate()
- user_map
dict
: Mapping of added Instagram users and theirUSER_MAPPING
- classmethod load(name, local=True)[source]View on GitHub
Loads an existing profile from a locally saved pickle file or remotely stored pickle bytes
- classmethod from_json(json_str)[source]View on GitHub
Creates a profile from a JSON formatted string of config settings
- Return type
- classmethod from_dict(d)[source]View on GitHub
Creates a profile from a dictionary of config settings
- Return type
- static profile_exists(name, local=True)[source]View on GitHub
Checks locally/remotely to see if a
Profile
with the specified name has an existing save fileWhenever the
name
is changed, its property setter calls this method to ensure you don’t accidentally overwrite a save that alreadyexists
- static get_local_path(name)[source]View on GitHub
Returns filepath of where a local profile would be saved
- Return type
- add_users(users, send_tweet=False)[source]View on GitHub
Add Instagram user(s) to the
user_map
for subsequent monitoringNote
By default, newly added users won’t have their posts tweeted the first time they’re scraped
The IDs of the ~12 most recent posts are stored in the
scraped
listAny new posts from that point forward will be tweeted
You can override this by setting
send_tweet=True
This causes their ~12 most recent posts to be scraped AND tweeted
- add_hashtags(user, hashtags)[source]View on GitHub
Add hashtag(s) to a user in the
user_map
, which will be randomly chosen from when composing Tweets
- save(name=None, alert=True)[source]View on GitHub
Pickles and saves the
Profile
using the specified or currently set name.
- validate()[source]View on GitHub
Checks to see if the Profile is fully configured for InstaTweeting
- Raises
ValueError – if the
session_id
,twitter_keys
, oruser_map
are invalid
- to_pickle()[source]View on GitHub
Serializes profile to a pickled byte string
- Return type
- to_json()[source]View on GitHub
Serializes profile to a JSON formatted string
- Return type
- to_dict()[source]View on GitHub
Serializes profile to a dict
- Return type
- view_config()[source]View on GitHub
Prints the
config
dict to make it legible
- property exists: bool
Returns True if a local save file or database record exists for the currently set profile name
- property profile_path: str
If
local
isTrue
, returns the file path for where this profile would be/is saved
- get_user(user)[source]View on GitHub
Returns the specified user’s dict entry in the
user_map
- Return type
- get_scraped_from(user)[source]View on GitHub
Returns a list of posts that have been scraped from the specified user
- Return type
- get_tweets_for(user)[source]View on GitHub
Returns a list of tweets that use the specified user’s scraped content
- Return type
- get_hashtags_for(user)[source]View on GitHub
Returns the hashtag list for the specified user
- Return type
- property local: bool
Indicates if saves should be made locally (
True
) or on a remote database (False
)- Return type
- property name: str
A name for the Profile
The
name
is used differently depending on the value oflocal
local==True
: the name determines theprofile_path
(path where it would save to)local==False
: the name is used as the primary key in theProfiles
database table
…
Profile Names Must Be Unique
When you set or change the
name
, a property setter will make sure noprofile_exists()
with that name before actually updating itThis ensures that you don’t accidentally overwrite a different Profile’s save data
…
- Raises
FileExistsError – if
local
==True
and a save is found in theLOCAL_DIR
ResourceWarning – if
local
==False
and a database row is found byquery_profile()
- property session_id: str
Instagram
sessionid
cookie, obtained by logging in through a browser- Tip
If you log into your account with a browser you don’t use, the session cookie will last longer
- property twitter_keys: dict
Twitter developer API keys with v1.1 endpoint access. See
DEFAULT_KEYS
The db
module
The db
module contains the DBConnection
class and the Profiles
database table
The Database Table
In the Profiles
database table each row corresponds to a unique Profile
- The table only has two fields per row:
name
: primary key for lookups/insertionsconfig
: stores the Profile as pickle bytes viato_pickle()
How is profile data saved to the database?
When a Profile
calls save()
and has local
= False
, it will
connect()
to the database specified by the DABATASE_URL
environment variable and use it
to query_profile()
settings
If the
profile_exists()
in the database already, itsconfig
data will be updatedOtherwise, the
DBConnection
willsave_profile()
data in a new table row
Important!!
You MUST configure the DATABASE_URL
environment variable to save/load remotely
InstaTweet uses
SQLAlchemy
to create aDBConnection
– any db it supports is compatibleSee the
db
module for more information
One Last Thing!
The DBConnection
is meant to be used as a context manager
with DBConnection() as db:
# Do Something
A
SESSION
is created/destroyed when saving, loading, and InstaTweeting aProfile
If you don’t want that, here’s instructions on Persisting The DBConnection
…
- InstaTweet.db.DATABASE_URL
The Database URL to use, obtained from the
DATABASE_URL
environment variable
…
- class InstaTweet.db.Profiles(**kwargs)[source]View on GitHub
Database table used for storing
Profile
settingsThe table currently has only 2 fields, for the
name
and pickle bytes of the profile- config
The pickle bytes from
Profile.to_pickle()
…
- class InstaTweet.db.DBConnection[source]View on GitHub
Database Connection class with context management ooh wow
Uses
SQLAlchemy
to connect and interact with the database specified byDATABASE_URL
environment variableSample Usage:
def poop_check(): with DBConnection() as db: if db.query_profile(name="POOP").first(): raise FileExistsError('DELETE THIS NEPHEW......')
- SESSION
The currently active session; closed on object exit
- Type
- ENGINE
The engine for the currently set
DATABASE_URL
; reused after first connection- Type
- static connect()[source]View on GitHub
Creates a
scoped_session
and assigns it toDBConnection.SESSION
- query_profile(name)[source]View on GitHub
Queries the database for a
Profile
by its name- Parameters
name (str) – the profile name (ie. the
Profile.name
)- Returns
- Return type
- load_profile(name)[source]View on GitHub
Loads a profile from the database by name
- Parameters
name (str) – the profile name (ie. the
Profile.name
)- Raises
LookupError – if the database has no profile saved with the specified name
- Return type
- save_profile(profile, alert=True)[source]View on GitHub
Saves a
Profile
to the database by either updating an existing row or inserting a new one
- delete_profile(name, alert=True)[source]View on GitHub
Deletes a
Profile
from the database by name- Parameters
name (str) – the profile name (ie. the
Profile.name
)alert (bool) – if
True
, will print a message upon successfully deleting
- Return type
The TweetClient
class
- class InstaTweet.tweetclient.TweetClient(profile, proxies=None)[source]View on GitHub
Bases:
object
- MAX_HASHTAGS = 5
- DEFAULT_KEYS = {'Access Token': 'string', 'Consumer Key': 'string', 'Consumer Secret': 'string', 'Token Secret': 'string'}
- __init__(profile, proxies=None)[source]View on GitHub
Initialize TweetClient using a
Profile
Basically just a wrapper for tweepy. It uses the settings of a profile to initialize the API and send tweets
- Parameters
profile (Profile) – the profile to use when initializing a
tweepy.API
objectproxies (Optional[dict]) – optional proxies to use when making API requests
- get_api()[source]View on GitHub
Initializes a
API
object using the API keys of the loadedProfile
- Return type
- static get_oauth(api_keys)[source]View on GitHub
Initializes and returns an
OAuth1UserHandler
object from tweepy using the specified API keys- Parameters
api_keys (dict) – Twitter developer API keys with v1.1 endpoint access
- Return type
- send_tweet(post, hashtags=None)[source]View on GitHub
Composes and sends a Tweet using an already-downloaded Instagram post
- Parameters
- Return type
How Tweets are Composed and Sent
The
InstaPost.filepath
– set bydownload_post()
– is used as the media sourceThe body of the tweet is then generated by
build_tweet()
as folows:The
InstaPost.caption
is used as a starting pointIf you’ve
add_hashtags()
for the user, will randomlypick_hashtags()
to includeLastly, the
InstaPost.permalink
is added to the end
- upload_media(post)[source]View on GitHub
Uploads the media from an already-downloaded Instagram post to Twitter
Note
If the post is a carousel, only the first 4 photos/videos will be uploaded
- build_tweet(post, hashtags=None)[source]View on GitHub
Uses an
InstaPost
to build the body text of a tweet
- static pick_hashtags(hashtags)[source]View on GitHub
Randomly picks hashtags from the provided list and returns them as a single string
The number of hashtags chosen will either be 1 less than the length of the list (to avoid using the same tags in every tweet), or the value of
MAX_HASHTAGS
, whichever is smaller- Parameters
hashtags (list[str]) – a list of hashtags to randomly choose from
- Example
from InstaTweet import TweetClient >> TweetClient.pick_hashtags(['cat','dog','woof']) "#woof #cat\n"
- Return type
Note
A newline is added to help with formatting & character counting in
build_tweet()
The InstaClient
class
- InstaTweet.instaclient.USER_AGENT
Hardcoded user agent proven to work with the
get_user()
endpoint introduced in v2.0.0b13
- InstaClient.DOWNLOAD_DIR
[Optional] – Directory to temporarily download media to
- class InstaTweet.instaclient.InstaClient(session_id, user_agent=USER_AGENT, proxies=None)[source]View on GitHub
Bases:
object
Minimalistic class for scraping/downloading Instagram user/media data
- __init__(session_id, user_agent=USER_AGENT, proxies=None)[source]View on GitHub
Initialize an
InstaClient
with an Instagram sessionid cookie (at minimum)Note
As of v2.0.0b13, the endpoint used by
get_user()
seems to require a specificUSER_AGENT
You can override the hardcoded one if you’d like, but you’ll likely get a"useragent mismatch"
response
- request(url)[source]View on GitHub
Sends a request using the
cookies
,headers
, andproxies
- Parameters
url (str) – the Instagram URL to send the request to
- Return type
Response
- get_user(username)[source]View on GitHub
Scrapes an Instagram user’s profile and wraps the response
- download_post(post, filepath=None)[source]View on GitHub
Downloads the media from an Instagram post
The InstaUser
class
- class InstaTweet.instauser.InstaUser(data, client=None)[source]View on GitHub
Bases:
object
Minimalistic API response wrapper for an Instagram profile
- __init__(data, client=None)[source]View on GitHub
Initialize an
InstaUser
- Parameters
data (dict) – the API response JSON to use as source data
client (Optional[InstaClient]) – API client to use; only required for
get_more_posts()
- get_more_posts()[source]View on GitHub
Requests the next page of posts
If the user
has_more_posts
, they’ll be added to theposts
list- Returns
True
if the request was successful, otherwiseFalse
- Return type
- property has_more_posts: bool
Returns
True
if more posts can be scraped usingget_more_posts()
- property end_cursor: str
Cursor used in request by
get_more_posts()
The InstaPost
class
- class InstaTweet.instapost.InstaPost(post_data)[source]View on GitHub
Bases:
object
Minimalistic API response wrapper for an Instagram post
- __init__(post_data)[source]View on GitHub
Initialize an
InstaPost
- id
The post id
- is_video
Indicates if the post is a video or photo
- filepath
str
: Path of downloaded media, set bydownload_post()
- tweet_data
dict
: Limited data from a successful tweet based off this post, set bysend_tweet()
- property media_url: str
The direct URL to the actual post content
- Returns
the
video_url
if the post is a video, otherwise thethumbnail_url
- property filename: str
Concatenates
id
+filetype
to create the default filename, for use when saving the post- For Example::
>> print(post.filename) “2868062811604347946.mp4”
- add_tweet_data(tweet)[source]View on GitHub
Used by
TweetClient
to add minimal tweet data after the post has been tweeted
The utils
module
This module contains a few helper functions that are used throughout the package
- InstaTweet.utils.get_agents()[source]View on GitHub
Scrapes a list of user agents. Returns a default list if the scrape fails.
Note
Deprecated since 2.0.0b13, but might be useful when new endpoint gets patched
- Return type
- InstaTweet.utils.get_agent(index=0)[source]View on GitHub
Returns a single user agent string from the specified index of the AGENTS list
Note
Deprecated since 2.0.0b13, but might be useful when new endpoint gets patched
- Return type
- InstaTweet.utils.get_proxies(env_key)[source]View on GitHub
Retrieve proxies from an environment variable
- InstaTweet.utils.get_root()[source]View on GitHub
- Return type
- InstaTweet.utils.get_filepath(filename, filetype='txt')[source]View on GitHub
- Return type
Just want to get started?
If you don’t care about the details and just want to get this running… I get you.
You’ll only need to be familiar with
The
InstaTweet
class, which is used tostart()
the “main script”The
db
module, but only if you plan to save data remotely
Otherwise, the other classes are pretty self explanatory
Tip
InstaClient
sends requests to InstagramTweetClient
wraps thetweepy.API
tosend_tweet()
based off anInstaPost
The
db
module contains theProfiles
database table and theDBConnection
class
InstaTweet Snippets
About the User Map
About the User Map
The user_map
is a dict containing info about the users added to a Profile
It’s used to help detect new posts and compose tweets on a per-user basis
Entries are created when you
add_users()
, which map the user to aUSER_MAPPING
The
USER_MAPPING
maintains lists of hashtags, scraped posts, and sent tweetsThe mapping is updated when you
add_hashtags()
and successfullysend_tweet()
You can access entries in the user_map
as follows:
get_user()
allows you to retrieve a full entry by usernameget_hashtags_for()
,get_scraped_from()
,get_tweets_for()
provide access to lists
Saving a Profile
Saving a Profile
When you save()
your Profile
, the current or specified name
will be used to create or update a save file in the location specified by local
From the Docs…
- Profile.save(name=None, alert=True)[source]View on GitHub
Pickles and saves the
Profile
using the specified or currently set name.
- InstaTweet.profile.Profile.local =True
Indicates if saves should be made locally (
True
) or on a remote database (False
)- Return type
Important!!
You MUST configure the DATABASE_URL
environment variable to save/load remotely
InstaTweet uses SQLAlchemy
to create a DBConnection
Any
SQLAlchemy
-supported database is therefore also supported byInstaTweet
See the
db
module for more information
Persisting The DBConnection
You can assign a DBConnection()
to a variable if you want a persistent connection
Here’s how:
from InstaTweet import DBConnection
# When __enter__ is called for the first time, the engine is set
>>> with DBConnection() as db:
... pass
# Since the database URL is constant,
#__exit__() doesn't remove the ENGINE class var
>>> print(db.ENGINE)
Engine(postgresql://...)
# The SESSION class var is cleared upon __exit__ though
>>> print(db.SESSION)
None
- To connect to the database and create a new session, call
connect()
It will persist until you somehow trigger a call to
__exit__()
# Using the DBConnection object from above
# Call connect() to create a new connection
>>> db.connect()
# Now it can be used like a regular object, and the
# connection will persist until you trigger a call to __exit__()
>>> profile = db.load_profile('myProfile')
>>> profile.view_config()
Output:
name : myProfile
local : True
session_id :
twitter_keys : {'Consumer Key': 'string', 'Consumer Secret': 'string', 'Access Token': 'string', 'Token Secret': 'string'}
user_agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36
proxy_key : None
user_map : {}
yea
Schedule InstaTweet
You can easily schedule InstaTweet using the provided scheduler script
#scheduler.py
from InstaTweet import InstaTweet
PROFILES = ['aProfile', 'myProfile']
LOCAL = True
def run(profile_name: str, local: bool = LOCAL):
"""Loads and InstaTweets a profile
:param profile_name: the name of the :class:`~.Profile`
:param local: if the profile is saved locally or in a SQLAlchemy supported database
"""
insta_tweet = InstaTweet.load(profile_name, local=local)
insta_tweet.start()
if __name__ == '__main__':
for profile in PROFILES:
run(profile, local=LOCAL)