├── examples └── login.py ├── LICENSE ├── README.md └── twttrapi.py /examples/login.py: -------------------------------------------------------------------------------- 1 | from twttrapi import TwttrAPIClient 2 | from getpass import getpass 3 | 4 | api_key = "your_rapidapi_key_here" 5 | client = TwttrAPIClient(api_key) 6 | 7 | username = input("Username/Email: ") 8 | password = getpass() 9 | 10 | r = client.login_email_username(username, password) 11 | 12 | if "success" in r and r["success"] == True: 13 | print("Session: " + r["session"]) 14 | 15 | else: 16 | if "errors" in r: 17 | print("Error: " + r["errors"][0]["message"]) 18 | 19 | elif "login_data" in r: 20 | while True: 21 | login_data = r["login_data"] 22 | resp = getpass(r["message"] + ": ") 23 | 24 | r = client.login_2fa(login_data, resp) 25 | 26 | if "login_data" in r: 27 | pass 28 | 29 | elif r["success"] == True: 30 | print("Session: " + r["session"]) 31 | break 32 | 33 | else: 34 | print("Error: " + r["error"]) 35 | break 36 | 37 | else: 38 | print("Error: Can't login.") 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Aimadnet 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TwttrAPI Python - Unofficial Twitter API 2 | 3 | A Python API wrapper for TwttrAPI, an unofficial Twitter API available on RapidAPI, which is built using Twitter's mobile API. 4 | 5 | [https://rapidapi.com/twttrapi-twttrapi-default/api/twttrapi](https://rapidapi.com/twttrapi-twttrapi-default/api/twttrapi) 6 | 7 | ## Installation 8 | 9 | Copy the `twttrapi.py` file into your project directory. 10 | 11 | ## Usage 12 | 13 | Import the `TwttrAPIClient` class and instantiate it with your RapidAPI key: 14 | 15 | ```python 16 | from twttrapi import TwttrAPIClient 17 | 18 | api_key = "your_rapidapi_key_here" 19 | client = TwttrAPIClient(api_key) 20 | ``` 21 | 22 | ## Methods 23 | 24 | Here is a list of methods available in the `TwttrAPIClient` class: 25 | 26 | * `get_tweet(tweet_id)` 27 | * `get_tweet_conversation(tweet_id)` 28 | * `user_tweets(username=None, user_id=None, cursor=None)` 29 | * `user_media(username=None, user_id=None, cursor=None)` 30 | * `user_likes(username=None, user_id=None, cursor=None)` 31 | * `for_you_timeline(cursor=None)` 32 | * `following_timeline(cursor=None)` 33 | * `create_tweet(tweet_text, attachment_url=None, in_reply_to_tweet_id=None, media_id=None)` 34 | * `delete_tweet(tweet_id)` 35 | * `get_user(username=None)` 36 | * `user_followers(username=None, user_id=None, cursor=None)` 37 | * `user_following(username=None, user_id=None, cursor=None)` 38 | * `search_suggestions(query, cursor=None)` 39 | * `search_top(query, cursor=None)` 40 | * `search_latest(query, cursor=None)` 41 | * `search_users(query, cursor=None)` 42 | * `search_images(query, cursor=None)` 43 | * `search_videos(query, cursor=None)` 44 | * `login_email_username(username_or_email, password)` 45 | * `login_2fa(login_data, response)` 46 | * `logout()` 47 | * `follow_user(username=None, user_id=None)` 48 | * `unfollow_user(username=None, user_id=None)` 49 | * `favorite_tweet(tweet_id)` 50 | * `unfavorite_tweet(tweet_id)` 51 | * `retweet_tweet(tweet_id)` 52 | * `unretweet_tweet(tweet_id)` 53 | * `get_dm_conversations(cursor=None)` 54 | * `get_dm_conversation(username=None, user_id=None, cursor=None)` 55 | * `send_dm(message, to_user_name=None, to_user_id=None, media_id=None)` 56 | * `upload_image(image_url)` 57 | 58 | For more information on each method and its parameters, please refer to the `twttrapi.py` file. 59 | 60 | ## Example 61 | 62 | Here's an example on how to use the API wrapper: 63 | 64 | ```python 65 | from twttrapi import TwttrAPIClient 66 | 67 | api_key = "your_rapidapi_key_here" 68 | client = TwttrAPIClient(api_key) 69 | 70 | # Get a tweet by its ID 71 | tweet_id = "1652849795336159233" 72 | tweet = client.get_tweet(tweet_id) 73 | print(tweet) 74 | ``` 75 | -------------------------------------------------------------------------------- /twttrapi.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | class TwttrAPIClient: 4 | def __init__(self, api_key, session="", proxy=""): 5 | self.api_key = api_key 6 | self.base_url = "https://twttrapi.p.rapidapi.com/" 7 | self.twttr_session = session 8 | self.twttr_proxy = proxy 9 | 10 | def _get_headers(self): 11 | return { 12 | "twttr-session": self.twttr_session, 13 | "twttr-proxy": self.twttr_proxy, 14 | "x-rapidapi-host": "twttrapi.p.rapidapi.com", 15 | "x-rapidapi-key": self.api_key, 16 | "content-type": "application/json", 17 | } 18 | 19 | def _send_request(self, method, endpoint, params=None, data=None): 20 | url = self.base_url + endpoint 21 | headers = self._get_headers() 22 | 23 | if method == "POST": 24 | headers["content-type"] = "application/x-www-form-urlencoded" 25 | 26 | response = requests.request(method, url, headers=headers, params=params, data=data) 27 | response.raise_for_status() 28 | 29 | return response.json() 30 | 31 | def get_tweet(self, tweet_id): 32 | endpoint = "get-tweet" 33 | params = { 34 | "tweet_id": tweet_id 35 | } 36 | return self._send_request("GET", endpoint, params) 37 | 38 | def get_tweet_conversation(self, tweet_id): 39 | endpoint = "get-tweet-conversation" 40 | params = { 41 | "tweet_id": tweet_id 42 | } 43 | return self._send_request("GET", endpoint, params) 44 | 45 | def user_tweets(self, username=None, user_id=None, cursor=None): 46 | endpoint = "user-tweets" 47 | params = { 48 | "username": username, 49 | "user_id": user_id, 50 | "cursor": cursor 51 | } 52 | return self._send_request("GET", endpoint, params) 53 | 54 | def user_media(self, username=None, user_id=None, cursor=None): 55 | endpoint = "user-media" 56 | params = { 57 | "username": username, 58 | "user_id": user_id, 59 | "cursor": cursor 60 | } 61 | return self._send_request("GET", endpoint, params) 62 | 63 | def user_likes(self, username=None, user_id=None, cursor=None): 64 | endpoint = "user-likes" 65 | params = { 66 | "username": username, 67 | "user_id": user_id, 68 | "cursor": cursor 69 | } 70 | return self._send_request("GET", endpoint, params) 71 | 72 | def for_you_timeline(self, cursor=None): 73 | endpoint = "for-you-timeline" 74 | params = { 75 | "cursor": cursor 76 | } 77 | return self._send_request("GET", endpoint, params) 78 | 79 | def following_timeline(self, cursor=None): 80 | endpoint = "following-timeline" 81 | params = { 82 | "cursor": cursor 83 | } 84 | return self._send_request("GET", endpoint, params) 85 | 86 | def create_tweet(self, tweet_text, attachment_url=None, in_reply_to_tweet_id=None, media_id=None): 87 | endpoint = "create-tweet" 88 | data = { 89 | "tweet_text": tweet_text, 90 | "attachment_url": attachment_url, 91 | "in_reply_to_tweet_id": in_reply_to_tweet_id, 92 | "media_id": media_id 93 | } 94 | return self._send_request("POST", endpoint, data=data) 95 | 96 | def delete_tweet(self, tweet_id): 97 | endpoint = "delete-tweet" 98 | params = { 99 | "tweet_id": tweet_id 100 | } 101 | return self._send_request("GET", endpoint, params) 102 | 103 | def get_user(self, username=None): 104 | endpoint = "get-user" 105 | params = { 106 | "username": username 107 | } 108 | return self._send_request("GET", endpoint, params) 109 | 110 | def user_followers(self, username=None, user_id=None, cursor=None): 111 | endpoint = "user-followers" 112 | params = { 113 | "username": username, 114 | "user_id": user_id, 115 | "cursor": cursor 116 | } 117 | return self._send_request("GET", endpoint, params) 118 | 119 | def user_following(self, username=None, user_id=None, cursor=None): 120 | endpoint = "user-following" 121 | params = { 122 | "username": username, 123 | "user_id": user_id, 124 | "cursor": cursor 125 | } 126 | return self._send_request("GET", endpoint, params) 127 | 128 | def search_suggestions(self, query, cursor=None): 129 | endpoint = "search-suggestions" 130 | params = { 131 | "query": query, 132 | "cursor": cursor 133 | } 134 | return self._send_request("GET", endpoint, params) 135 | 136 | def search_top(self, query, cursor=None): 137 | endpoint = "search-top" 138 | params = { 139 | "query": query, 140 | "cursor": cursor 141 | } 142 | return self._send_request("GET", endpoint, params) 143 | 144 | def search_latest(self, query, cursor=None): 145 | endpoint = "search-latest" 146 | params = { 147 | "query": query, 148 | "cursor": cursor 149 | } 150 | return self._send_request("GET", endpoint, params) 151 | 152 | def search_users(self, query, cursor=None): 153 | endpoint = "search-users" 154 | params = { 155 | "query": query, 156 | "cursor": cursor 157 | } 158 | return self._send_request("GET", endpoint, params) 159 | 160 | def search_images(self, query, cursor=None): 161 | endpoint = "search-images" 162 | params = { 163 | "query": query, 164 | "cursor": cursor 165 | } 166 | return self._send_request("GET", endpoint, params) 167 | 168 | def search_videos(self, query, cursor=None): 169 | endpoint = "search-videos" 170 | params = { 171 | "query": query, 172 | "cursor": cursor 173 | } 174 | return self._send_request("GET", endpoint, params) 175 | 176 | def login_email_username(self, username_or_email, password): 177 | endpoint = "login-email-username" 178 | data = { 179 | "username_or_email": username_or_email, 180 | "password": password 181 | } 182 | return self._send_request("POST", endpoint, data=data) 183 | 184 | def login_2fa(self, login_data, response): 185 | endpoint = "login-2fa" 186 | data = { 187 | "login_data": login_data, 188 | "response": response 189 | } 190 | return self._send_request("POST", endpoint, data=data) 191 | 192 | def logout(self): 193 | endpoint = "logout" 194 | return self._send_request("POST", endpoint) 195 | 196 | def follow_user(self, username=None, user_id=None): 197 | endpoint = "follow-user" 198 | data = { 199 | "username": username, 200 | "user_id": user_id 201 | } 202 | return self._send_request("POST", endpoint, data=data) 203 | 204 | def unfollow_user(self, username=None, user_id=None): 205 | endpoint = "unfollow-user" 206 | data = { 207 | "username": username, 208 | "user_id": user_id 209 | } 210 | return self._send_request("POST", endpoint, data=data) 211 | 212 | def favorite_tweet(self, tweet_id): 213 | endpoint = "favorite-tweet" 214 | data = { 215 | "tweet_id": tweet_id 216 | } 217 | return self._send_request("POST", endpoint, data=data) 218 | 219 | def unfavorite_tweet(self, tweet_id): 220 | endpoint = "unfavorite-tweet" 221 | data = { 222 | "tweet_id": tweet_id 223 | } 224 | return self._send_request("POST", endpoint, data=data) 225 | 226 | def retweet_tweet(self, tweet_id): 227 | endpoint = "retweet-tweet" 228 | data = { 229 | "tweet_id": tweet_id 230 | } 231 | return self._send_request("POST", endpoint, data=data) 232 | 233 | def unretweet_tweet(self, tweet_id): 234 | endpoint = "unretweet-tweet" 235 | data = { 236 | "tweet_id": tweet_id 237 | } 238 | return self._send_request("POST", endpoint, data=data) 239 | 240 | def get_dm_conversations(self, cursor=None): 241 | endpoint = "get-dm-conversations" 242 | params = { 243 | "cursor": cursor 244 | } 245 | return self._send_request("GET", endpoint, params) 246 | 247 | def get_dm_conversation(self, username=None, user_id=None, cursor=None): 248 | endpoint = "get-dm-conversation" 249 | params = { 250 | "username": username, 251 | "user_id": user_id, 252 | "cursor": cursor 253 | } 254 | return self._send_request("GET", endpoint, params) 255 | 256 | def send_dm(self, message, to_user_name=None, to_user_id=None, media_id=None): 257 | endpoint = "send-dm" 258 | data = { 259 | "message": message, 260 | "to_user_name": to_user_name, 261 | "to_user_id": to_user_id, 262 | "media_id": media_id 263 | } 264 | return self._send_request("POST", endpoint, data=data) 265 | 266 | def upload_image(self, image_url): 267 | endpoint = "upload-image" 268 | data = { 269 | "image_url": image_url 270 | } 271 | return self._send_request("POST", endpoint, data=data) --------------------------------------------------------------------------------