This workflow corresponds to n8n.io template #9568 — we link there as the canonical source.
This workflow follows the Google Sheets → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "ptwolWvQwd2VnU5e",
"name": "Auto Scrape X Posts & Publish to Telegram copy 2",
"tags": [],
"nodes": [
{
"id": "260d511b-12b8-4dfb-93d9-6d0317c49dea",
"name": "Remove Duplicates",
"type": "n8n-nodes-base.removeDuplicates",
"position": [
512,
-112
],
"parameters": {
"options": {
"historySize": 10000
},
"operation": "removeItemsSeenInPreviousExecutions",
"dedupeValue": "={{ $json.tweet_id }}"
},
"typeVersion": 2
},
{
"id": "863dc17e-446c-4118-9171-0db7402b967f",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-16,
224
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "a13ca579-f044-4900-94f2-675d012ffa64",
"name": "Trigger : Start scraping on X",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-512,
-112
],
"parameters": {},
"typeVersion": 1
},
{
"id": "1939f7d2-4ebd-459c-aaaa-8c4f5fdd0e94",
"name": "Twitter API",
"type": "n8n-nodes-base.httpRequest",
"position": [
-272,
-112
],
"parameters": {
"url": "https://api.twitterapi.io/twitter/user/last_tweets",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "userID",
"value": "1361142028667662338"
},
{
"name": "userName",
"value": "@Inku_Fr"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "9a988b26-1746-4175-b0ff-92c06f391d99",
"name": "Filter only tweets that have text and an image",
"type": "n8n-nodes-base.code",
"position": [
256,
-112
],
"parameters": {
"jsCode": "// Filter only tweets that have text and an image\nreturn items\n .map(item => {\n return {\n json: {\n author_name: item.json.author_name,\n author_username: item.json.author_username,\n tweet_text: item.json.tweet_text,\n tweet_url: item.json.tweet_url,\n tweet_id: item.json.tweet_id,\n created_at: item.json.created_at,\n image_url: item.json.first_image_url // retrieve the image link\n }\n };\n })\n .filter(item => item.json.tweet_text && item.json.image_url); // only keeps tweets with text AND images\n"
},
"typeVersion": 2
},
{
"id": "93da9f3b-fea4-4d56-a900-298891ccd28d",
"name": "Save the scraping Data in a google sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-512,
224
],
"parameters": {
"columns": {
"value": {
"URL": "={{ $json.tweet_url }}",
"Date": "={{ $json.created_at }}",
"Image": "={{ $json.image_url }}",
"Contenu": "={{ $json.tweet_text }}",
"ID Tweet": "={{ $json.tweet_id }}",
"Nom du compte": "={{ $json.author_name }}",
"Nom d'utilisateur": "={{ $json.author_username }}"
},
"schema": [
{
"id": "ID Tweet",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID Tweet",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Contenu",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Contenu",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Image",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Image",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom d'utilisateur",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Nom d'utilisateur",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom du compte",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Nom du compte",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MSy_TwbRjl_IprnzZp9yX_W8pLeVxPd1c_gNnJgtykY/edit#gid=0",
"cachedResultName": "Feuille 1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1xZbBYTPYAW-625aRFwfxNzkTA-nbVY7Mv_EX3ubk1uQ",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xZbBYTPYAW-625aRFwfxNzkTA-nbVY7Mv_EX3ubk1uQ/edit?usp=drivesdk",
"cachedResultName": "INSTANT ANIME"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "4fc30aa0-ef16-4865-80f4-1b8e7d924d4f",
"name": "Format and remove links from the scraping data",
"type": "n8n-nodes-base.code",
"position": [
-272,
224
],
"parameters": {
"jsCode": "// Filter and clean tweets\nreturn $input.all()\n .map(item => {\n let text = item.json.Contenu;\n\n // Removes links\n text = text.replace(/https?:\\/\\/\\S+/g, '').trim();\n\n return {\n json: {\n author_name: item.json[\"Nom du compte\"],\n author_username: item.json[\"Nom d'utilisateur\"],\n tweet_text: text,\n tweet_url: item.json.URL,\n tweet_id: item.json[\"ID Tweet\"],\n created_at: item.json.Date,\n first_image_url: item.json.Image,\n }\n };\n })\n // Only keep tweets that have text and an image\n .filter(item => item.json.tweet_text && item.json.first_image_url);\n"
},
"typeVersion": 2
},
{
"id": "f3495493-6a6a-48b8-979d-35e246583fc3",
"name": "Wait 3 minutes per post",
"type": "n8n-nodes-base.wait",
"position": [
512,
240
],
"parameters": {
"unit": "minutes",
"amount": 3
},
"typeVersion": 1.1
},
{
"id": "83ca9695-a6d7-4ed5-86c5-8455ecbf984e",
"name": "Send a photo and text in your channel",
"type": "n8n-nodes-base.telegram",
"position": [
256,
240
],
"parameters": {
"file": "={{ $json.first_image_url }}",
"chatId": "=@instantanimee",
"operation": "sendPhoto",
"additionalFields": {
"caption": "={{ $json.tweet_text }}"
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "6d359557-113a-4b5a-ae02-df43ecf98a67",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-368,
-272
],
"parameters": {
"color": 6,
"width": 256,
"height": 352,
"content": "## Enter the ID and username of the user account you want to scrape."
},
"typeVersion": 1
},
{
"id": "f36be26a-4ae5-4e8a-b52b-d1b78726328a",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-64,
-272
],
"parameters": {
"color": 6,
"width": 784,
"height": 352,
"content": "## It will format the data. It also filters the tweets, keeping only those that contain text and at least one image."
},
"typeVersion": 1
},
{
"id": "7fa0a416-8c2e-48dd-9aab-144d9f2afd82",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-592,
144
],
"parameters": {
"color": 6,
"width": 1312,
"height": 320,
"content": "## Publish the tweet on your telegram channel with a wait time of 3 minutes per post"
},
"typeVersion": 1
},
{
"id": "09e7411e-dca4-43ad-8cb9-4f0e95f5448f",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1488,
-480
],
"parameters": {
"width": 624,
"height": 1216,
"content": "\n\n## Who\u2019s it for\n\nThis automation template is designed for content creators, social media managers, and automation enthusiasts who want to automatically scrape X (Twitter) posts with images and publish them directly to a Telegram channel \u2014 without writing a single line of code.\n\n## How it works\n\n- Trigger: Start scraping from a specific X (Twitter) account using its ID and username.\n\n- Fetch data: The workflow calls the Twitter API to collect recent tweets.\n\n- Format data: Extracts fields such as author name, username, tweet text, tweet URL, tweet ID, creation date, images, and video URL.\n\n- Filter: Keeps only tweets that contain text and at least one image.\n\n- Remove duplicates: Ensures no repeated tweets are processed.\n\n- Save: Stores the cleaned tweet data into a Google Sheet for backup and future use.\n\n- Clean text: Removes unnecessary links from the tweet text before publishing.\n\n- Loop & Publish: Iterates over the filtered tweets and sends them (text + image) to your Telegram channel.\n\n- Delay: Waits 3 minutes between each post to avoid spamming.\n\n## How to use\n\n- Enter the Twitter ID and username of the account you want to scrape.\n\n- Connect your Google Sheets account to store the data.\n\n- Connect your Telegram bot and channel where the posts will be published.\n\n- Start the workflow \u2192 tweets will be scraped, filtered, saved, and automatically published on Telegram.\n\n## Requirements\n\n- A valid Twitter API connection or scraping endpoint.\n\n- A Google Sheet for storing scraped tweets.\n\n- A Telegram Bot connected to your channel.\n\n- n8n or any automation tool where this workflow runs.\n\n## \u2753 Need help\n\n**Contact me for consulting and support:** [LinkedIn](https://www.linkedin.com/in/jaures-nya-83a033270/) / [YouTube](https://www.youtube.com/@jauresnya) \n"
},
"typeVersion": 1
},
{
"id": "5641d972-fc52-4c85-8a30-5ecbf6308852",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-816,
-480
],
"parameters": {
"color": 7,
"width": 1792,
"height": 1056,
"content": "## Use this workflow to automates the process of scraping tweets from X (Twitter) and publishing them to a Telegram channel\n### What problem is this workflow solving? / Use case\nMy workflow is solving the problem of automating content curation and cross-posting from Twitter to Telegram, while keeping it clean, organized, spam-free, and consistent."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "e1819680-5476-42e8-8fc1-56098c8e04b6",
"connections": {
"Twitter API": {
"main": [
[
{
"node": "Filter only tweets that have text and an image",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "Send a photo and text in your channel",
"type": "main",
"index": 0
}
]
]
},
"Remove Duplicates": {
"main": [
[
{
"node": "Save the scraping Data in a google sheet",
"type": "main",
"index": 0
}
]
]
},
"Wait 3 minutes per post": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Trigger : Start scraping on X": {
"main": [
[
{
"node": "Twitter API",
"type": "main",
"index": 0
}
]
]
},
"Send a photo and text in your channel": {
"main": [
[
{
"node": "Wait 3 minutes per post",
"type": "main",
"index": 0
}
]
]
},
"Save the scraping Data in a google sheet": {
"main": [
[
{
"node": "Format and remove links from the scraping data",
"type": "main",
"index": 0
}
]
]
},
"Filter only tweets that have text and an image": {
"main": [
[
{
"node": "Remove Duplicates",
"type": "main",
"index": 0
}
]
]
},
"Format and remove links from the scraping data": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleSheetsOAuth2ApihttpHeaderAuthtelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This automation template is designed for content creators, social media managers, and automation enthusiasts who want to automatically scrape X (Twitter) posts with images and publish them directly to a Telegram channel — without writing a single line of code.
Source: https://n8n.io/workflows/9568/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
checkProcess(old). Uses googleSheets, httpRequest, telegram, @n-octo-n/n8n-nodes-json-database. Event-driven trigger; 40 nodes.
checkProcess. Uses googleSheets, httpRequest, telegram, @n-octo-n/n8n-nodes-json-database. Event-driven trigger; 40 nodes.
This template monitors Google Drive folder for new files, extracts text from PDFs, images, text files, CSVs, and Google Docs., reads images with meta/llama-3.2-11b-vision-instruct, structures the resu
This workflow provides a complete solution for handling Telegram Stars payments, invoicing and refunds using n8n. It automates the process of sending invoices, managing pre-checkout approvals, recordi
clients kept booking meetings during my prayer times. i'd either miss a prayer or scramble to reschedule. the problem wasn't the clients — it was that my calendar had no blocked windows for salah. i n