👻 Shadowban Checker
Check if your account is shadowbanned. Tests search visibility, reply visibility, and ghost ban status.
📋 What It Does
This script provides the following capabilities:
- Automated operation — Runs directly in your browser console on x.com
- Configurable settings — Customize behavior via the CONFIG object
- Real-time progress — Shows live status updates with emoji-coded logs
- Rate limiting — Built-in delays to respect X/Twitter's rate limits
- Data export — Results exported as JSON/CSV for further analysis
Use cases:
- Check if your account is shadowbanned. Tests search visibility, reply visibility, and ghost ban status.
- Automate repetitive analytics tasks on X/Twitter
- Save time with one-click automation — no API keys needed
- Works in any modern browser (Chrome, Firefox, Edge, Safari)
⚠️ Important Notes
Use responsibly! All automation should respect X/Twitter's Terms of Service. Use conservative settings and include breaks between sessions.
- This script runs in the browser DevTools console — not Node.js
- You must be logged in to x.com for the script to work
- Start with low limits and increase gradually
- Include random delays between actions to appear human
- Don't run multiple automation scripts simultaneously
🌐 Browser Console Usage
Steps:
- Go to
x.com/YOUR_USERNAME - Open browser console (
F12→ Console tab) - Copy and paste the script from
src/shadowbanChecker.js - Press Enter to run
/**
* ============================================================
* 🕵️ Shadowban Checker — Production Grade
* ============================================================
*
* @name shadowbanChecker.js
* @description Check if your X/Twitter account is shadowbanned.
* Tests: search ban, ghost ban, reply deboosting,
* suggestion ban, and media visibility.
* @author nichxbt (https://x.com/nichxbt)
* @version 1.0.0
* @date 2026-02-24
* @repository https://github.com/nirholas/XActions
*
* ============================================================
* 📋 USAGE:
*
* 1. Go to: https://x.com (any page, logged in)
* 2. Open DevTools Console (F12)
* 3. Paste this script and press Enter
* 4. Enter the username to check when prompted (or edit CONFIG)
*
* WHAT IT CHECKS:
* ┌─────────────────────────────────────────────────────────┐
* │ Test │ What it means │
* ├─────────────────────┼───────────────────────────────────┤
* │ Search Suggestion │ Profile appears in search bar │
* │ Search Ban │ Tweets appear in search results │
* │ Ghost Ban │ Replies visible to other users │
* │ Reply Deboosting │ Replies hidden behind "Show more" │
* │ Media Ban │ Media shows in search results │
* └─────────────────────────────────────────────────────────┘
* ============================================================
*/
(() => {
'use strict';
const CONFIG = {
username: '', // Leave empty = check your own account
verboseLogging: true, // Show detailed test steps
testDelay: 3000, // Delay between tests (ms)
};
// ══════════════════════════════════════════════════════════
// 🔧 Utilities
// ══════════════════════════════════════════════════════════
const sleep = ms => new Promise(r => setTimeout(r, ms + ms * 0.1 * (Math.random() - 0.5)));
const fetchPage = async (url) => {
try {
const resp = await fetch(url, {
credentials: 'include',
headers: { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' },
});
if (!resp.ok) return { status: resp.status, text: '' };
const text = await resp.text();
return { status: resp.status, text };
} catch (e) {
return { status: 0, text: '', error: e.message };
}
};
// ══════════════════════════════════════════════════════════
// 🚀 Main
// ══════════════════════════════════════════════════════════
(async () => {
const W = 60;
console.log('╔' + '═'.repeat(W) + '╗');
console.log('║ 🕵️ SHADOWBAN CHECKER' + ' '.repeat(W - 23) + '║');
console.log('║ by nichxbt — v1.0' + ' '.repeat(W - 21) + '║');
console.log('╚' + '═'.repeat(W) + '╝');
// Determine username
let username = CONFIG.username;
if (!username) {
// Try to detect from page
const metaEl = document.querySelector('meta[property="al:android:url"]');
const metaContent = metaEl?.getAttribute('content') || '';
const metaMatch = metaContent.match(/screen_name=([^&]+)/);
if (metaMatch) {
username = metaMatch[1];
} else {
// Try from header
const navLink = document.querySelector('a[data-testid="AppTabBar_Profile_Link"]');
const href = navLink?.getAttribute('href') || '';
const hrefMatch = href.match(/^\/([A-Za-z0-9_]+)/);
if (hrefMatch) username = hrefMatch[1];
}
}
if (!username) {
console.error('❌ Could not detect username. Set CONFIG.username manually.');
return;
}
console.log(`\n🔍 Checking @${username} for shadowban indicators...\n`);
const results = {
username,
timestamp: new Date().toISOString(),
tests: {},
overallStatus: 'UNKNOWN',
};
const log = (msg) => CONFIG.verboseLogging && console.log(` ${msg}`);
// ── Test 1: Account Exists ──────────────────────────────
console.log('━'.repeat(50));
console.log(' 📋 Test 1: Account Existence');
console.log('━'.repeat(50));
const profileResp = await fetchPage(`https://x.com/${username}`);
if (profileResp.status === 404 || profileResp.text.includes('This account doesn')) {
console.error(`❌ Account @${username} does not exist or is suspended.`);
results.tests.exists = { status: 'FAIL', detail: 'Account not found' };
results.overallStatus = 'SUSPENDED';
console.log('\n📊 Result: Account appears SUSPENDED or DELETED.\n');
return;
}
if (profileResp.text.includes('Account suspended') || profileResp.text.includes('suspended')) {
console.error(`❌ Account @${username} is SUSPENDED.`);
results.tests.exists = { status: 'FAIL', detail: 'Suspended' };
results.overallStatus = 'SUSPENDED';
return;
}
results.tests.exists = { status: 'PASS', detail: 'Account exists and is active' };
console.log(' ✅ Account exists and is active');
await sleep(CONFIG.testDelay);
// ── Test 2: Search Suggestion Ban ───────────────────────
console.log('\n━'.repeat(50));
console.log(' 📋 Test 2: Search Suggestion Ban');
console.log('━'.repeat(50));
log('Checking if @' + username + ' appears in typeahead search...');
try {
// Use X's internal typeahead API
const typeaheadResp = await fetch(
`https://x.com/i/api/1.1/search/typeahead.json?q=${username}&src=search_box&result_type=users`,
{ credentials: 'include', headers: { 'x-twitter-active-user': 'yes' } }
);
if (typeaheadResp.ok) {
const data = await typeaheadResp.json();
const found = data.users?.some(u =>
u.screen_name?.toLowerCase() === username.toLowerCase()
);
if (found) {
results.tests.searchSuggestion = { status: 'PASS', detail: 'Appears in search suggestions' };
console.log(' ✅ Appears in search suggestions — no suggestion ban');
} else {
results.tests.searchSuggestion = { status: 'FAIL', detail: 'NOT in search suggestions' };
console.log(' ⚠️ NOT appearing in search suggestions — possible suggestion ban');
}
} else {
results.tests.searchSuggestion = { status: 'UNKNOWN', detail: `API returned ${typeaheadResp.status}` };
console.log(' ❓ Could not check (API returned ' + typeaheadResp.status + ')');
}
} catch (e) {
results.tests.searchSuggestion = { status: 'UNKNOWN', detail: e.message };
console.log(' ❓ Could not check: ' + e.message);
}
await sleep(CONFIG.testDelay);
// ── Test 3: Search Ban ──────────────────────────────────
console.log('\n━'.repeat(50));
console.log(' 📋 Test 3: Search Ban');
console.log('━'.repeat(50));
log('Searching for tweets from @' + username + '...');
try {
const searchResp = await fetchPage(`https://x.com/search?q=from%3A${username}&f=live`);
if (searchResp.text.includes(username)) {
results.tests.searchBan = { status: 'PASS', detail: 'Tweets appear in search' };
console.log(' ✅ Tweets appear in search results — no search ban');
} else {
results.tests.searchBan = { status: 'WARN', detail: 'Tweets may not appear in search' };
console.log(' ⚠️ Tweets may not appear in search — possible search ban');
}
} catch (e) {
results.tests.searchBan = { status: 'UNKNOWN', detail: e.message };
console.log(' ❓ Could not check: ' + e.message);
}
await sleep(CONFIG.testDelay);
// ── Test 4: Ghost Ban (Reply Visibility) ────────────────
console.log('\n━'.repeat(50));
console.log(' 📋 Test 4: Ghost Ban (Reply Visibility)');
console.log('━'.repeat(50));
log('Checking reply thread visibility...');
try {
// Search for replies from the user
const replyResp = await fetchPage(`https://x.com/search?q=from%3A${username}%20filter%3Areplies&f=live`);
if (replyResp.text.includes(username)) {
results.tests.ghostBan = { status: 'PASS', detail: 'Replies appear visible' };
console.log(' ✅ Replies appear in search — no ghost ban detected');
} else {
results.tests.ghostBan = { status: 'WARN', detail: 'Replies may be hidden' };
console.log(' ⚠️ Replies may be hidden — possible ghost ban');
}
} catch (e) {
results.tests.ghostBan = { status: 'UNKNOWN', detail: e.message };
console.log(' ❓ Could not check: ' + e.message);
}
await sleep(CONFIG.testDelay);
// ── Test 5: Media Search Ban ────────────────────────────
console.log('\n━'.repeat(50));
console.log(' 📋 Test 5: Media Visibility');
console.log('━'.repeat(50));
log('Checking if media tweets appear in search...');
try {
const mediaResp = await fetchPage(`https://x.com/search?q=from%3A${username}%20filter%3Amedia&f=live`);
if (mediaResp.text.includes(username)) {
results.tests.mediaBan = { status: 'PASS', detail: 'Media visible in search' };
console.log(' ✅ Media appears in search — no media ban');
} else {
results.tests.mediaBan = { status: 'WARN', detail: 'Media may not appear in search' };
console.log(' ⚠️ Media may not appear in search — possible media ban');
}
} catch (e) {
results.tests.mediaBan = { status: 'UNKNOWN', detail: e.message };
console.log(' ❓ Could not check: ' + e.message);
}
// ── Overall Assessment ──────────────────────────────────
const testValues = Object.values(results.tests);
const fails = testValues.filter(t => t.status === 'FAIL').length;
const warns = testValues.filter(t => t.status === 'WARN').length;
const passes = testValues.filter(t => t.status === 'PASS').length;
if (fails > 0) results.overallStatus = 'LIKELY SHADOWBANNED';
else if (warns >= 2) results.overallStatus = 'POSSIBLY SHADOWBANNED';
else if (warns === 1) results.overallStatus = 'MINOR ISSUES';
else results.overallStatus = 'CLEAN';
// ── Final Report ────────────────────────────────────────
console.log('\n\n╔' + '═'.repeat(W) + '╗');
console.log('║ 📊 SHADOWBAN CHECK RESULTS' + ' '.repeat(W - 29) + '║');
console.log('╠' + '═'.repeat(W) + '╣');
for (const [test, result] of Object.entries(results.tests)) {
const icon = result.status === 'PASS' ? '✅' : result.status === 'FAIL' ? '❌' : result.status === 'WARN' ? '⚠️' : '❓';
const line = `${icon} ${test}: ${result.detail}`;
console.log('║ ' + line.padEnd(W - 2) + '║');
}
console.log('╠' + '═'.repeat(W) + '╣');
const statusIcon = results.overallStatus === 'CLEAN' ? '✅' :
results.overallStatus.includes('LIKELY') ? '❌' : '⚠️';
const statusLine = `${statusIcon} Overall: ${results.overallStatus}`;
console.log('║ ' + statusLine.padEnd(W - 2) + '║');
console.log('╚' + '═'.repeat(W) + '╝');
// Tips
if (results.overallStatus !== 'CLEAN') {
console.log('\n💡 Tips to resolve shadowban:');
console.log(' 1. Stop all automated activity for 48-72 hours');
console.log(' 2. Remove any rule-violating content');
console.log(' 3. Verify your email and phone number');
console.log(' 4. Don\'t use third-party apps aggressively');
console.log(' 5. Engage naturally — like, reply, browse');
console.log(' 6. Wait — most shadowbans resolve in 24-48 hours');
}
// Save results
try {
localStorage.setItem(
`xactions_shadowban_${username}`,
JSON.stringify(results)
);
console.log(`\n💾 Results saved. Compare over time with:`);
console.log(` JSON.parse(localStorage.getItem("xactions_shadowban_${username}"))`);
} catch {}
console.log('');
})();
})();
⚙️ Configuration
| Setting | Default | Description |
|---|---|---|
username |
'', |
Leave empty = check your own account |
verboseLogging |
true, |
Show detailed test steps |
testDelay |
3000, |
Delay between tests (ms) |
📖 Step-by-Step Tutorial
Step 1: Navigate to the right page
Open your browser and go to x.com/YOUR_USERNAME. Make sure you're logged in to your X/Twitter account.
Step 2: Open the browser console
- Chrome/Edge: Press
F12orCtrl+Shift+J(Mac:Cmd+Option+J) - Firefox: Press
F12orCtrl+Shift+K - Safari: Enable Developer menu in Preferences → Advanced, then press
Cmd+Option+C
Step 3: Paste the script
Copy the entire script from src/shadowbanChecker.js and paste it into the console.
Step 4: Customize the CONFIG (optional)
Before running, you can modify the CONFIG object at the top of the script to adjust behavior:
const CONFIG = {
// Edit these values before running
// See Configuration table above for all options
};
Step 5: Run and monitor
Press Enter to run the script. Watch the console for real-time progress logs:
- ✅ Green messages = success
- 🔄 Blue messages = in progress
- ⚠️ Yellow messages = warnings
- ❌ Red messages = errors
Step 6: Export results
Most scripts automatically download results as JSON/CSV when complete. Check your Downloads folder.
🖥️ CLI Usage
You can also run this via the XActions CLI:
# Install XActions globally
npm install -g xactions
# Run via CLI
xactions --help
🤖 MCP Server Usage
Use with AI agents (Claude, Cursor, etc.) via the MCP server:
# Start MCP server
npm run mcp
See the MCP Setup Guide for integration with Claude Desktop, Cursor, and other AI tools.
📁 Source Files
| File | Description |
|---|---|
src/shadowbanChecker.js |
Main script |
🔗 Related Scripts
| Script | Description |
|---|---|
| Account Health Monitor | Comprehensive health check for your X/Twitter account |
| Audience Demographics | Analyze your follower demographics including bio keywords, locations, account age, and interests |
| Audience Overlap | Compare the follower lists of two accounts to find audience overlap |
| Engagement Leaderboard | Analyze who engages most with your tweets |
| Follower Growth Tracker | Track your follower count over time |
Author: nich (@nichxbt) — XActions on GitHub
⚡ Ready to try � Shadowban Checker?
XActions is 100% free and open-source. No API keys, no fees, no signup.
Browse All Scripts