coercive / botkicker
Coercive Security BotKicker
Requires
- php: >=7.4
Requires (Dev)
- phpunit/phpunit: ^12
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- 0.1.0
- 0.0.81
- 0.0.80
- 0.0.79
- 0.0.78
- 0.0.77
- 0.0.76
- 0.0.75
- 0.0.74
- 0.0.73
- 0.0.72
- 0.0.71
- 0.0.70
- 0.0.69
- 0.0.68
- 0.0.67
- 0.0.66
- 0.0.65
- 0.0.64
- 0.0.63
- 0.0.62
- 0.0.61
- 0.0.60
- 0.0.59
- 0.0.58
- 0.0.57
- 0.0.56
- 0.0.55
- 0.0.54
- 0.0.53
- 0.0.52
- 0.0.51
- 0.0.50
- 0.0.49
- 0.0.48
- 0.0.47
- 0.0.46
- 0.0.45
- 0.0.44
- 0.0.43
- 0.0.42
- 0.0.41
- 0.0.40
- 0.0.39
- 0.0.38
- 0.0.37
- 0.0.36
- 0.0.35
- 0.0.34
- 0.0.33
- 0.0.32
- 0.0.31
- 0.0.30
- 0.0.29
- 0.0.28
- 0.0.27
- 0.0.26
- 0.0.25
- 0.0.24
- 0.0.23
- 0.0.22
- 0.0.21
- 0.0.20
- 0.0.19
- 0.0.18
- 0.0.17
- 0.0.16
- 0.0.15
- 0.0.14
- 0.0.13
- 0.0.12
- 0.0.11
- 0.0.10
- 0.0.9
- 0.0.8
- 0.0.7
- 0.0.6
- 0.0.5
- 0.0.4
- 0.0.3
- 0.0.2
- 0.0.1
This package is auto-updated.
Last update: 2026-10-13 14:19:36 UTC
README
A simple detection based on black list
Get
composer require coercive/botkicker
Compatible PHP 7.4 → 8.5
Tests
composer install
vendor/bin/phpunit
PHPUnit 12 requires PHP 8.3+ to run the tests ; the library itself still runs on PHP 7.4.
Some tests download the dynamic IP lists (Google, Bing, Facebook, LinkedIn : network and whois command needed), skip them with :
vendor/bin/phpunit --exclude-group network
List infos
-
PERISHABLE PRESS ULTIMATE USER-AGENT BLACKLIST https://perishablepress.com/4g-ultimate-user-agent-blacklist/
-
PERISHABLE PRESS ULTIMATE REFERRER BLACKLIST https://perishablepress.com/4g-ultimate-referrer-blacklist/
-
CHONGQED REFERER BLACKLIST http://blacklist.chongqed.org/
-
MITCHELL KROG - BlackList file from apache set https://github.com/mitchellkrogza
Warning info
Some terms where placed in ambiguous list because of too large detection. You can find this ambiguous file are in each list directory. (work in progress)
List items are regular expressions (case insensitive, delimited by backticks).
Kicker system
| Kicker | Automatic input (from $_SERVER, $_GET, $_POST) |
Coercive lists |
|---|---|---|
UserAgentKicker |
HTTP_USER_AGENT |
loadCoerciveLists(), loadCoerciveGraylist(), loadPerishableBlacklist(), loadMitchellKrogzaBlacklist() |
RefererKicker |
HTTP_REFERER |
loadCoerciveList(), loadPerishableList(), loadChongqedList() |
RequestMethodKicker |
REQUEST_METHOD |
loadCoerciveList() |
UrlKicker |
REQUEST_URI (or SCRIPT_URL), without query |
loadCoerciveLists(), loadCoerciveGraylist() |
InputKicker |
$_GET and $_POST values |
loadCoerciveLists(), loadCoerciveGraylist() |
IpKicker |
none : use setInputList() |
loadCoerciveList() |
Basics
use Coercive\Security\BotKicker\UserAgentKicker; # Get Instance $kicker = new UserAgentKicker; // or other kicker # Load a default list $kicker->loadCoerciveLists(); # or load custom list... # Basic bot detection if(!$kicker->detect()->getStatus()) { echo 'a bot is detected'; } else { # True if in whitelist or not in blacklist }
You can detect if UA need the robots.txt
if($kicker->isRobotsTxtRequested()) { /* do something */ }
(Dis)Allow empty
# You can (dis)allow empty current detection $kicker->allowEmpty( true | false );
Handle custom elements to verify
# Example of custom datas $datas = ['bot1', 'bot2', 'bot3']; # Override auto detection $kicker->setInputList($datas); # Or add to auto detection $kicker->addToInputList($datas); # Show detection result $status = $kicker->detect(); var_dump( $status->getStatus() ); # bool if ok or not var_dump( $status->getMatches() ); # array list of match elements var_dump( $status->getInput() ); # string the input that match var_dump( $status->getInputs() ); # array current datas
Handle custom list
You can set your own list (array format)
$kicker->setBlackList([ 'bad', 'bad too' ]); $kicker->setWhiteList([ 'good', 'good too' ]);
Or from file (txt brut format : one item per line, lines beginning with # are skipped)
$kicker->setBlackListFromFiles([ '/path/file1', '/path/file2' ]); $kicker->setWhiteListFromFiles([ '/path/file1', '/path/file2' ]);
If some list are already loaded, you can add some items like that
$kicker->addToBlackList([ 'bad', 'bad too' ]); $kicker->addToWhiteList([ 'good', 'good too' ]);
UrlKicker / InputKicker only
use Coercive\Security\BotKicker\InputKicker; use Coercive\Security\BotKicker\UrlKicker; $url = new UrlKicker; # or new UrlKicker(false) without automatic detection $url->setUrl('/some/url?query=1'); # cleaned to /some/url $url->getUrl(); $url->getRawUrl(); $url->isMalformed(); # url with ellipsis "..." or ending with "/null" $url->find('some'); $input = new InputKicker(true, false); # $_GET only $input->isValidUtf8(); $input->containsUrl(); # the first url found or empty string
IpKicker only
IpKicker provides some IP / CIDR lists (static or dynamic), to use in your own firewall rules.
use Coercive\Security\BotKicker\IpKicker; $ipk = new IpKicker; # Local files $ipk->getBingList(); $ipk->getBrevoList(); $ipk->getCloudflareList(); $ipk->getLetsEncryptList(); $ipk->getMailjetList(); $ipk->getStripeList(); # Static $ipk->getMoneticoList(); $ipk->getPayboxList(); $ipk->getPayPlugList(); $ipk->getProlexisList(); # Dynamic (download) : IPv4 by default, IPv6 with true $ipk->getBingList(true); # throws RuntimeException on failure $ipk->getGoogleBotList(); $ipk->getGoogleCloudList(); $ipk->getGoogleUserList(); $ipk->getGoogleSpecialCrawlersList(); $ipk->getGoogleUserTriggeredFetchersList(); $ipk->getGoogleUserTriggeredFetchersGoogleList(); # Dynamic (whois command) $ipk->getFacebookList(); $ipk->getLinkedInList(); $ipk->getFromASN('AS32934'); # IPv4 and IPv6, or false (IPv4) / true (IPv6)
Host / Ns Look Up
Get the domains list from IP
use Coercive\Security\BotKicker\HostLookUp; use Coercive\Security\BotKicker\NsLookUp; $look = new HostLookUp; # OR $look = new NsLookUp; $array = $look->getDomains('111.22.33.4');
Get the ip list from domain
use Coercive\Security\BotKicker\HostLookUp; use Coercive\Security\BotKicker\NsLookUp; $look = new HostLookUp; # OR $look = new NsLookUp; $array = $look->getIps('www.example.com.');
Match item
use Coercive\Security\BotKicker\HostLookUp; use Coercive\Security\BotKicker\NsLookUp; $look = new HostLookUp; # OR $look = new NsLookUp; # Match ip > domain (the domain itself or one of its subdomains) $bool = $look->match('66.249.66.1', 'googlebot.com'); # OR match with reverse (match ip > domain first and domain > ip after) $bool = $look->match('66.249.66.1', 'googlebot.com', true); # OR with PHP native functions (IPv4 only, no shell command) $bool = $look->matchNative('66.249.66.1', 'googlebot.com', true);
ModSecurity audit log
use Coercive\Security\BotKicker\ModSec\ModSecLogParser; $parser = new ModSecLogParser('/var/log/apache2/modsec_audit.log'); foreach ($parser->filterUnallowedMethodRequests() as $entry) { echo $entry->getIp(), ' ', $entry->getMethod(), ' ', $entry->getHost(), $entry->getUri(), PHP_EOL; } # Also : getEntries(), search(callable), filterAccessByIp(), filterGetRequests(), filterPostRequests(), filterHeadRequests(), filterOptionsRequests()
UFW syslog
use Coercive\Security\BotKicker\Syslog\SyslogUfw; $ufw = new SyslogUfw('/var/log/ufw.log'); foreach ($ufw->getMatches() as $ip => $entity) { if($entity->isBlocked()) { echo $ip, ' ', implode(',', $entity->getPorts()), PHP_EOL; } } # Unparsable lines $ufw->getErrors();