Import Tweets into Google Sheets with Apps Script (2026)
Use one Apps Script to import tweets into Google Sheets: new posts become rows, ids never repeat, an hourly trigger runs it, and your key stays hidden.
Tarun Khatri
Published · Updated · 7 min read
To import tweets into Google Sheets, use an Apps Script that fetches new posts, adds each as a row, and runs on a timer.
This Twitter to Google Sheets guide is for you if you want X (Twitter) posts in a sheet that fills itself. You get one script, tested logic and real costs. We run Weir, the search API the script calls.
After Step 1, run this in the Apps Script editor to log your first posts:
function testWeir() {
const key = PropertiesService.getScriptProperties().getProperty("WEIR_API_KEY");
const body = JSON.stringify({ fromUsers: ["GoogleWorkspace"], limit: 3 });
const options = { method: "post", contentType: "application/json", payload: body };
options.headers = { Authorization: "Bearer " + key };
Logger.log(UrlFetchApp.fetch("https://api.weirapp.io/v1/x/search", options).getContentText());
}
You need a Google account and a free Weir key. Here is the map:
- Store the keyAdd WEIR_API_KEY under Script Properties.
- Call the searchUrlFetchApp.fetch posts JSON to Weir.
- Page to the endFollow meta.nextCursor until it is null.
- Skip known idsSearch with sinceId and check column A.
- Run on a timerA time-driven trigger calls it every hour.
Which ways to import tweets into Google Sheets still work?
Several top guides still describe X's old free plan. Here is what each route needs as of October 2026:
| Route | You need | Price, as listed | The catch |
|---|---|---|---|
| Twitter Archiver add-on | Google Sheets | Not available | Listing says unavailable |
| IFTTT applet | IFTTT Pro | $2.99 a month, billed yearly | 10 tweets per search check |
| API Connector + X API | X API credits, the add-on | $0.005 per post read | Add-on plan priced apart |
| Apps Script + Weir (here) | A Weir key | 1 credit a call, 1 per post | A third party, not X |
Each figure comes from the vendor's own page, checked on 22 October 2026.
Our pick: IFTTT if you won't code. Otherwise use this script, which you own and can change.
Step 1: Store your key in Script Properties
Open your sheet and rename a tab to Tweets. Then click Extensions > Apps Script.
In the editor, open Project Settings and click Add script property under Script Properties. Name it WEIR_API_KEY and paste your key.
A key in a cell is visible to anyone who can see the sheet. Script Properties stay out of the grid, and getProperty returns null if the name is wrong.
Step 2: Call a Twitter API from Google Sheets with UrlFetchApp
UrlFetchApp.fetch sends the request, and muteHttpExceptions lets you read Weir's error.
const API = "https://api.weirapp.io/v1/x/search";
function searchPage(body) {
const key = PropertiesService.getScriptProperties().getProperty("WEIR_API_KEY");
const response = UrlFetchApp.fetch(API, {
method: "post",
contentType: "application/json",
headers: { Authorization: "Bearer " + key },
payload: JSON.stringify(body),
muteHttpExceptions: true, // so you see Weir's error message
});
const code = response.getResponseCode();
if (code !== 200) throw new Error("Weir answered " + code + ": " + response.getContentText());
return JSON.parse(response.getContentText());
}
We ran this search for @GoogleWorkspace on 22 October 2026 with limit: 3. It returned three posts and a next-page cursor for 4 credits. The newest, trimmed:
{
"id": "2112952806294352206",
"text": "Staring at a blank document? 🫠 Just tell Gemini in Docs your goal. ...",
"url": "https://x.com/GoogleWorkspace/status/2112952806294352206",
"createdAt": "2026-10-21T17:03:00.000Z",
"likeCount": 222,
"retweetCount": 28,
"viewCount": 14850
}
Step 3: Page through results until the cursor is null
A busy search can return several pages between runs. This loop stops on a null cursor or after five pages.
const SEARCH = { fromUsers: ["GoogleWorkspace"], limit: 20 }; // or { query: "your brand" }
const MAX_PAGES = 5;
function fetchNewPosts(sinceId) {
const body = Object.assign({}, SEARCH);
if (sinceId) body.sinceId = sinceId; // only posts newer than your last row
let posts = [];
for (let page = 0; page < MAX_PAGES; page++) {
const result = searchPage(body);
posts = posts.concat(result.data);
if (!result.meta.nextCursor) break; // null is the only stop signal
body.cursor = result.meta.nextCursor;
}
return posts;
}
Never stop on an empty page alone. Weir's pagination docs say a page can be empty with more behind it.
Step 4: Export tweets to Google Sheets without duplicates
This reads the ids in column A, asks only for newer posts, and writes them oldest first.
function importTweets() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tweets");
const last = sheet.getLastRow();
const cells = last > 1 ? sheet.getRange(2, 1, last - 1, 1).getDisplayValues() : [];
const ids = cells.map((row) => row[0]);
const seen = new Set(ids);
const newest = ids.reduce((a, b) => (newer(b, a) ? b : a), "");
const fresh = fetchNewPosts(newest).filter((p) => !seen.has(p.id) && seen.add(p.id));
const rows = fresh.sort((a, b) => (newer(a.id, b.id) ? 1 : -1)).map(toRow);
if (rows.length) sheet.getRange(last + 1, 1, rows.length, rows[0].length).setValues(rows);
}
Two helpers finish it. newer compares ids as text, because they are too long for a number:
function toRow(p) {
const counts = [p.likeCount, p.retweetCount, p.viewCount];
return [p.id, p.createdAt, p.author.username, p.text].concat(counts, p.url);
}
function newer(a, b) {
return a.length !== b.length ? a.length > b.length : a > b;
}
In our test, the three posts landed like this:
| id | createdAt (UTC) | likes | views |
|---|---|---|---|
| 2112590420928545267 | 2026-10-20 17:03 | 26 | 5,445 |
| 2112907510982087063 | 2026-10-21 14:03 | 100 | 12,809 |
| 2112952806294352206 | 2026-10-21 17:03 | 222 | 14,850 |
The full text, username, reposts and link fill the other columns.
Step 5: Run it every hour with a time-driven trigger
Run setUp once from the editor: it formats column A, writes the headers and adds the trigger.
function setUp() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tweets");
sheet.getRange("A:A").setNumberFormat("@"); // plain text, so ids keep all 19 digits
const head = ["id", "createdAt", "username", "text", "likes", "reposts", "views", "url"];
sheet.getRange(1, 1, 1, head.length).setValues([head]);
ScriptApp.newTrigger("importTweets").timeBased().everyHours(1).create();
}
A second run would add a second trigger.
Google's trigger guide says the time "might be slightly randomized," and a failed run sends you an email.
Google's quotas for a free Gmail account, as of September 2026:
An hourly run uses a tiny share of that.
How we tested a script we couldn't run here
Apps Script only runs on Google's servers. So we ran the same file in Node, with stand-ins for the four Google services, fed with the real response above.
Nine checks passed, including these:
- First run: two calls, because the full page carried a cursor. Three rows were added, oldest first.
- Second run: it sent the newest id as
sinceIdand added nothing. - Page cap: a cursor that never ends stopped after five calls.
- Errors: a
402threw, so Google's failure email would reach you. - No plain text: our stand-in sheet rounded the ids, and the next
sinceIdfailed Weir's check.
How much does it cost to import tweets into Google Sheets?
Each call costs 1 credit plus 1 per post. A run that finds posts usually makes one more empty call to reach the null cursor. For one account posting 10 times a day:
Your 5,000 free monthly credits cover the first three. Price a busier search with the X API cost calculator.
For comparison, X's own API charges $0.005 per post read, so the same 300 posts cost $1.50 a month there.
If it doesn't work
Weir answered 401: the property name or key is wrong. CheckWEIR_API_KEYunder Script Properties.- Ids show in scientific notation: column A isn't plain text. Fix it, delete those rows, and run again.
- Rows with 0 likes: those are reposts. Put
-filter:nativeretweetsinSEARCH.queryto leave them out. Weir answered 402: you're out of credits. Top up; retrying won't help.
When not to use Weir
- Seconds matter. X's Activity API pushes posts as they happen.
- You'd rather not code. IFTTT's applets fit, if 10 posts per check is enough.
- A deal with X itself is required. Use the official X API and its own terms.
- Only your own archive matters. X's data download covers it; our Open Twitter Archive guide shows how.
FAQ
Can I import tweets into Google Sheets for free?
Yes, for small jobs. Weir's 5,000 free monthly credits cover an hourly import of an account posting 10 times a day. X's pricing page lists no free tier, and IFTTT's X applets need Pro.
Does Twitter Archiver still work?
No. Its Google Workspace Marketplace listing says it "is temporarily unavailable due to changes in the Twitter API." That listing was last updated on 17 April 2023.
Can I use the Twitter API in Google Sheets with my own token?
Yes. Send your X bearer token in the same Authorization header, then adapt searchPage and toRow to X's own parameters and fields. X bills $0.005 per post read, as of October 2026.
How do I send the same tweets to Discord or Telegram?
Use the same search and newest-id trick, then post each item to a chat. See our Twitter to Discord webhook guide or the Twitter to Telegram bot.
Sources
All checked on 22 October 2026:
- Apps Script, UrlFetchApp and HTTPResponse: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
- Apps Script, properties: https://developers.google.com/apps-script/guides/properties
- Apps Script, Sheet and Range: https://developers.google.com/apps-script/reference/spreadsheet/sheet
- Apps Script, time-driven triggers: https://developers.google.com/apps-script/reference/script/clock-trigger-builder and https://developers.google.com/apps-script/guides/triggers/installable
- Apps Script, quotas: https://developers.google.com/apps-script/guides/services/quotas
- Apps Script, bound scripts: https://developers.google.com/apps-script/guides/bound
- Google Sheets API, number format tokens (
@): https://developers.google.com/workspace/sheets/api/guides/formats - Tweet Archiver, Google Workspace Marketplace: https://workspace.google.com/marketplace/app/tweet_archiver/976886281542
- IFTTT X service and plans: https://ifttt.com/twitter and https://ifttt.com/plans
- Mixed Analytics, API Connector guide (updated 9 April 2026): https://mixedanalytics.com/knowledge-base/import-twitter-data-to-google-sheets/
- X API pricing: https://docs.x.com/x-api/getting-started/pricing
- X Activity API: https://docs.x.com/x-api/activity/introduction
- Weir docs: https://docs.weirapp.io/response-shapes, https://docs.weirapp.io/pagination, https://docs.weirapp.io/billing
- Weir call, 22 October 2026: search_x for @GoogleWorkspace, limit 3, 4 credits