一键导入
x-search
X.com (Twitter) search & data extraction — cari post dengan advanced operators, extract replies, scroll pagination. Browser-based via Patchright MCP.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
X.com (Twitter) search & data extraction — cari post dengan advanced operators, extract replies, scroll pagination. Browser-based via Patchright MCP.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Threads (threads.com) search & data extraction — cari post, extract comments/replies, scroll pagination. Browser-based via Patchright MCP.
Instagram automation via Patchright MCP — DM, like, comment, search, profile, get images. Browser-based (not API). Part of social-media-browser umbrella.
Threads (threads.com) automation via Patchright MCP — post, reply, like, repost, DM, search, profile. Column-based web UI, English. Part of social-media-browser umbrella.
X.com (Twitter) automation via Patchright MCP — post, reply, like, retweet, DM, search, profile. English UI. Part of social-media-browser umbrella.
| name | x-search |
| description | X.com (Twitter) search & data extraction — cari post dengan advanced operators, extract replies, scroll pagination. Browser-based via Patchright MCP. |
| triggers | ["cari di x","search x","search twitter","x search","twitter search","research x","cari data x","cari tweet","x-research"] |
| tools | ["mcp_patchright_browser_navigate","mcp_patchright_browser_click","mcp_patchright_browser_snapshot","mcp_patchright_browser_run_code","mcp_patchright_browser_wait_for","mcp_patchright_browser_scroll","mcp_patchright_browser_tabs"] |
Search X.com (Twitter), extract posts with full reply threads via Patchright MCP.
rickicode| Filter | URL |
|---|---|
| Top | https://x.com/search?q={query}&src=typed_query |
| Latest | https://x.com/search?q={query}&src=typed_query&f=live |
| People | https://x.com/search?q={query}&src=typed_query&f=user |
| Media | https://x.com/search?q={query}&src=typed_query&f=image |
"exact phrase" — exact matchfrom:username — posts by specific userto:username — replies to specific usersince:2026-01-01 / until:2026-06-30 — date rangemin_faves:1000 / min_retweets:100 / min_replies:50 — engagement thresholdfilter:links / filter:images / filter:videos — content typefilter:verified — only verified accounts-filter:replies — exclude replieslang:id / lang:en — language filterasync (page) => {
await page.waitForTimeout(5000);
return await page.evaluate(() => {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
return [...articles].slice(0, 10).map(article => {
const userNameEl = article.querySelector('[data-testid="User-Name"]');
const links = userNameEl?.querySelectorAll('a') || [];
const textEl = article.querySelector('[data-testid="tweetText"]');
const timeEl = article.querySelector('time');
// Extract card links (link preview cards) — these have actual external URLs
const cards = article.querySelectorAll('[data-testid="card.wrapper"]');
const cardLinks = [...cards].map(c => {
const a = c.querySelector('a');
return a ? a.href : null;
}).filter(Boolean);
return {
authorHandle: links[1]?.textContent?.trim() || '',
text: textEl?.textContent?.trim() || '',
tweetUrl: timeEl?.closest('a')?.href || '',
cardLinks: cardLinks,
};
});
});
}
Important: Most X posts about "AI free credits" don't have direct URLs in text. The actual external links are in card preview links ([data-testid="card.wrapper"]). These are t.co shortened URLs that redirect to the real destination. Always extract cardLinks for research/promo hunting.
async (page) => {
await page.waitForTimeout(5000);
return await page.evaluate(() => {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
return [...articles].map(article => {
const userNameEl = article.querySelector('[data-testid="User-Name"]');
const links = userNameEl?.querySelectorAll('a') || [];
const textEl = article.querySelector('[data-testid="tweetText"]');
const timeEl = article.querySelector('time');
const replyBtn = article.querySelector('[data-testid="reply"]');
const retweetBtn = article.querySelector('[data-testid="retweet"]');
const likeBtn = article.querySelector('[data-testid="like"]');
const viewsEl = article.querySelector('a[href*="/analytics"]');
const imgs = article.querySelectorAll('img[src*="pbs.twimg.com/media"]');
return {
authorName: links[0]?.textContent?.trim() || '',
authorHandle: links[1]?.textContent?.trim() || '',
authorUrl: links[0]?.href || '',
verified: !!article.querySelector('img[alt="Verified account"]'),
text: textEl?.textContent?.trim() || '',
timestamp: timeEl?.getAttribute('datetime') || '',
timeDisplay: timeEl?.textContent?.trim() || '',
url: timeEl?.closest('a')?.href || '',
replies: replyBtn?.getAttribute('aria-label') || '',
retweets: retweetBtn?.getAttribute('aria-label') || '',
likes: likeBtn?.getAttribute('aria-label') || '',
views: viewsEl?.textContent?.trim() || '',
images: [...imgs].map(i => i.src),
hasVideo: !!article.querySelector('video, [data-testid="videoPlayer"]'),
hasQuote: !!article.querySelector('[data-testid="quoteTweet"]'),
};
});
});
}
Navigate to post URL, then extract main post + replies:
async (page) => {
// Navigate to post first, then:
await page.waitForTimeout(5000);
// Scroll to load more replies
for (let i = 0; i < 3; i++) {
await page.evaluate(() => window.scrollBy(0, 1000));
await page.waitForTimeout(2000);
}
return await page.evaluate(() => {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
return [...articles].map((article, idx) => {
const userNameEl = article.querySelector('[data-testid="User-Name"]');
const links = userNameEl?.querySelectorAll('a') || [];
const textEl = article.querySelector('[data-testid="tweetText"]');
const timeEl = article.querySelector('time');
const likeBtn = article.querySelector('[data-testid="like"]');
const viewsEl = article.querySelector('a[href*="/analytics"]');
return {
authorName: links[0]?.textContent?.trim() || '',
authorHandle: links[1]?.textContent?.trim() || '',
verified: !!article.querySelector('img[alt="Verified account"]'),
text: textEl?.textContent?.trim() || '',
timestamp: timeEl?.getAttribute('datetime') || '',
likes: likeBtn?.getAttribute('aria-label') || '',
views: viewsEl?.textContent?.trim() || '',
isMainPost: idx === 0,
};
});
});
}
async (page, maxScrolls = 5) => {
let allTweets = [];
const seen = new Set();
for (let i = 0; i < maxScrolls; i++) {
const tweets = await page.evaluate(() => {
return [...document.querySelectorAll('article[data-testid="tweet"]')].map(a => ({
url: a.querySelector('time')?.closest('a')?.href || '',
text: a.querySelector('[data-testid="tweetText"]')?.textContent?.trim()?.substring(0, 100) || '',
}));
});
for (const t of tweets) {
if (t.url && !seen.has(t.url)) {
seen.add(t.url);
allTweets.push(t);
}
}
await page.evaluate(() => window.scrollBy(0, 2000));
await page.waitForTimeout(2000);
}
return { total: allTweets.length, tweets: allTweets };
}
window.scrollBy() to load more results.img[alt="Verified account"]./{user}/status/{id}.requests.head(url, allow_redirects=True) to get the actual destination URL. Filter out t.co/twitter.com/x.com from final candidates.[data-testid="card.wrapper"] selector for link preview cards. These contain the actual external URLs behind t.co shortlinks.waitForTimeout(5000).tabs(action='select') to switch.mcp.client.streamable_http.streamablehttp_client + ClientSession — NOT raw HTTP POST. See patchright-browser skill for full pattern.waitForTimeout(5000).tabs(action='select') to switch.