The below Python script uses Chromium via Playwright to scrape Donald Trump's posts at Truth Social every 20 minutes, to deposit them in cells O23 and O24 of a specified GoogleSheet. If it is text, it will post the text of the post. If it is an image-only post, we will post only the image. Of course, this is just what I do; you can modify it to do whatever you like with the output. I'm also tight on space, which is why I don't do things like give a timestamp for the most-recent post. To install dependencies, in terminal, enter: pip install playwright gspread oauth2client playwright install Google stuff: Create a service account in the Google Cloud Console. Enable the Google Sheets API for your project. Download the credentials.json file and place it in the same directory as your script. Share your Google Sheet with the service account's email address. For reference in case you run into incompatibilities, I'm running Python 3.11.3. Python script: from playwright.sync_api import sync_playwright import json import time import gspread from oauth2client.service_account import ServiceAccountCredentials import re import html def fetch_api_data(): api_url = "https://truthsocial.com/api/v1/accounts/107780257626128497/statuses" top_post_data = None with sync_playwright() as p: # Launch a browser with custom arguments for off-screen window browser = p.chromium.launch( headless=False, args=["--window-position=-10000,-10000"] # Launch Chromium off-screen ) context = browser.new_context() page = context.new_page() # Navigate to the main page to simulate browser behavior page.goto("https://truthsocial.com/@realDonaldTrump") # Fetch API data directly using the browser's environment print("Fetching API data...") response_text = page.evaluate( """ async (apiUrl) => { const response = await fetch(apiUrl); return await response.text(); // Return raw response text for debugging } """, api_url, ) # Parse the top-most post try: posts = json.loads(response_text) if posts and isinstance(posts, list): top_post = posts[0] # The first post in the array # Check if the post is a reblog (repost) if top_post.get("reblog"): post_content = top_post["reblog"] else: post_content = top_post # Initialize variables title = "No title found" description = "No description found" # Extract text content content_html = post_content.get("content", "") # Remove HTML tags and unescape HTML entities text_content = re.sub('<[^<]+?>', '', content_html) text_content = html.unescape(text_content).strip() # Extract media attachments media_attachments = post_content.get("media_attachments", []) # Determine the type of post and set title and description accordingly if text_content and media_attachments: # Post with both text and image title = text_content description = media_attachments[0].get("url", "No image URL found") elif text_content: # Text-only post title = text_content description = "" # No description for text-only post elif media_attachments: # Image-only post title = "Image Post" description = media_attachments[0].get("url", "No image URL found") else: # Neither text nor image print("No text or media attachments found in the top post.") top_post_data = (title, description) else: print("No posts available in the response.") except json.JSONDecodeError as e: print(f"Error parsing JSON: {e}") except Exception as e: print(f"An error occurred: {e}") # Close the browser browser.close() return top_post_data def append_to_google_sheet(data, starting_cell="A1"): try: # Define the scope and authenticate with the Google Sheets API scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"] creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope) client = gspread.authorize(creds) # Open the Google Sheet; replace YOURSPREADSHEETIDHERE with your google sheets spreadsheet ID sheet = client.open_by_url("https://docs.google.com/spreadsheets/d/YOURSPREADSHEETIDHERE/").sheet1 # Determine the starting row and column from the cell reference (e.g., A1) starting_row = int(''.join(filter(str.isdigit, starting_cell))) # Extract row number starting_col_letters = ''.join(filter(str.isalpha, starting_cell)).upper() # Extract column letters # Convert column letters to index (e.g., 'AA' -> 27) def column_letter_to_number(column_letters): number = 0 for char in column_letters: number = number * 26 + (ord(char) - ord('A') + 1) return number starting_col = column_letter_to_number(starting_col_letters) # Write data to the sheet starting from the specified cell if data: title, description = data current_row = starting_row sheet.update_cell(current_row, starting_col, title) sheet.update_cell(current_row + 1, starting_col, description) print(f"Data successfully written to Google Sheets starting at {starting_cell}.") else: print("No data to write.") except Exception as e: print(f"An error occurred while writing to Google Sheets: {e}") if __name__ == "__main__": while True: try: # Fetch data every 20 minutes print("Running scraper...") post_data = fetch_api_data() if post_data: append_to_google_sheet(post_data, starting_cell="A1") else: print("No new data fetched.") except Exception as e: print(f"An unexpected error occurred in the main loop: {e}") print("Sleeping for 20 minutes...") time.sleep(20 * 60) # 20 minutes in seconds