- Published on • 4 min read
Introduction
Twitter likes bans a lot, and more specifically shadowbans. It's very easy to get one as they are assigned by the built-in abnormal activity detection. They usually last 2-3 days, but users usually don't know it, as it allows access to content of others, but blocks others to banned account. So let's increase awareness by setting up the appropriate monitor.
Requirements
- Basic knowledge of javascript
- New Relic free/paid account
- Access to shadowban.eu
Characteristic of API monitor
- It ignores 5* errors, so in case api backend is down we don't get notification
- It ignores accounts without tweets
- It alerts when account is shadowbanned (search ban, suggestion ban etc.)
- It alerts when account doesn't exist or was deleted.
Request
https://shadowban.eu/.api/<USER>
it's the only url used by monitor.
User-Agent
is required. Without it 403 forbidden status code appears in response.
Response types
Assuming the response is 200. Below are the typical json replies from the server:
@Account doesn't exists:
{"timestamp": 123456789.123456, "profile": {"has_tweets": false, "screen_name": "Account", "exists": false}}
@Account has no tweets:
{"profile": {"has_tweets": false, "exists": true, "screen_name": "Account", "protected": false}, "timestamp": 123456789.123456}
@Account is ok:
{"profile": {"has_tweets": true, "sensitives": {"possibly_sensitive": 0, "counted": 79, "possibly_sensitive_editable": 24}, "protected": false, "exists": true, "screen_name": "Account"}, "tests": {"search": "0123456789123456789", "typeahead": true, "ghost": {"ban": false}, "more_replies": {"error": "EUNKNOWN"}}, "timestamp": 123456789.123456}
@Account has shadowban
{"profile": {"has_tweets": true, "sensitives": {"possibly_sensitive": 0, "counted": 79, "possibly_sensitive_editable": 24}, "protected": false, "exists": true, "screen_name": "Account"}, "tests": {"search": "false", "typeahead": false, "ghost": {"ban": true}, "more_replies": {"error": "EUNKNOWN"}}, "timestamp": 123456789.123456}
It's not easy to notice, that in case of ban search
key gets value false
, but without ban it points to id of founded tweet 0123456789123456789
(from above example).
Monitor script
With proper research it's much easier to write a monitor script. It took me some time to understand API behaviour of this particular service. Feel free to copy and use below code. If you are not familiar with synthetic monitors in New Relic, go to documentation. It's nothing more than 2 clicks of the mouse. The only action here is changing variable USER
with different account name.
Please set period
time of monitor to something longer than 10 minutes. Site shadowban.eu is free for everyone and shadowban lasts 2-3 days, so there is no need to know if ban is active every 1 minute. Same with number of locations. One is enough, two should be max. Thank you.
/**
* This is NewRelic synthetic monitor script.
* It checks if user has shadowban on twitter
*/
var USER = 'VV0JC13CH'
var URL = 'https://shadowban.eu/.api/' + USER;
var assert = require('assert');
var options = {
//Define endpoint URL.
url: URL,
headers: {
'Accept': 'application/json',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0',
}};
$http.get(options, function(error, response, body) {
console.log(response.statusCode + " status code")
console.log(body)
if (response.statusCode == 200){
var json = JSON.parse(body)
var test_account_exists = json["profile"]["exists"]
var test_has_tweets = json["profile"]["has_tweets"]
if (test_has_tweets== true && test_account_exists == true){
console.log('@' + USER + ' account exists')
console.log('@' + USER + ' has tweets')
var test_search = json["tests"]["search"]
var test_typeahead = json["tests"]["typeahead"]
var ghost_ban = json["tests"]["ghost"]["ban"]
if (test_search == false){
console.log('Search Ban')
}
else{
console.log('No Search Ban')
}
if (test_typeahead == false){
console.log('Search Suggestion Ban')
}
else{
console.log('No Search Suggestion Ban')
}
if (ghost_ban == true){
console.log('Ghost Ban')
}
else{
console.log('No Ghost Ban')
}
assert.ok(ghost_ban == false, 'Ghost ban detected');
assert.ok(test_search != false, 'Search ban detected');
assert.ok(test_typeahead != false, 'Search suggestion ban detected');
}
else {
assert.ok(test_exists != false, 'Account @' + USER + 'does not exist');
console.log('Account has no tweets. Skipping ghost ban tests.')
}
}
else{
// This script doesn't alert when API server is up or down:
assert.ok(response.statusCode >= 500 && response.statusCode <= 520, response.statusCode + ' HTTP response status code');
}
}
);
Example output
200 status code
@vv0jc13ch account exists
@vv0jc13ch has tweets
No Search Ban
No Search Suggestion Ban
No Ghost Ban
Known limitation
If shadowban on Twitter is active and shadowban.eu will go down. Monitor is going to resolve incident and create next one when API will be once again available.
Good luck with bans! I hope you are kind to others :-)