Package: botblock
BotBlockA modern, self-hosted, privacy-respecting, CAPTCHA solutionTable of ContentsOverviewImplementation DetailsUsageInstallationGenerating a Simple CAPTCHAUsing the CAPTCHA EngineCustomizing CAPTCHA SettingsAvailable SettingsExample CAPTCHAsOverviewBotBlock is a CAPTCHA solution designed to help developers protect their websites and applications from bots, without having to compromise on the privacy of their users.Unlike most other CAPTCHA solutions, BotBlock is open source, completely self-hosted, and does not require JavaScript.If you are looking for a simple—yet robust—CAPTCHA solution that is customizable, easy to implement, privacy-respecting, and fully self-contained, BotBlock is the way to go!Implementation DetailsBotBlock is written in Python3 and designed to be fully compatible with modern web application frameworks, such as Django. It is perfect for small to large (and maybe even some corporate-sized) websites and projects looking to mitigate spam on their servers.BotBlock can be used to protect sensitive, costly, or limited resources that have the potential to be abused, such as storage space, email traffic, third-party API queries, human processing time, etc. For example, using BotBlock to guard a website's forms from automated submissions could mean the difference between a server that crashes after its drive is filled up (resulting in data loss, downtime, and hundreds of hours manual database entry review), and a perfectly healthy server that is able to reject the automated submissions without breaking a sweat.BotBlock strives to make it easy to generate all types CAPTCHAs. It supplies built-in defaults that work "out of the box," while also providing support for extensive customization, allowing developers to set custom fonts, character sets, image sizes and formats, minimum color contrast levels, and much more. BotBlock doesn't just focus on front-end content generation, however. Understanding that proper CAPTCHA validation is just as important as impressive CAPTCHA generation, BotBlock provides a backend CAPTCHA Engine designed to ensure the secure validation of CAPTCHAs. The Engine will automatically enforce CAPTCHA expirations and timeouts, utilize memory-efficient authentication schemes, prevent replay attacks, and much more. Ready for production environments, upon instantiation, the Engine will also launch dedicated subprocesses for generation and validation, and create a pool of CAPTCHAs to keep on standby. These features increase efficiency and allow for burstability, while ensuring that responses to CAPTCHA generation or validation queries are lightning fast.When using BotBlock for your project, it's important to keep accessibility in mind. Although BotBlock does provide font/image size and color contrast settings to help developers comply with modern web accessibility standards, BotBlock is not perfect. For example, at the moment, BotBlock does not provide support for audio-based CAPTCHAs, and due to the unique purpose of a CAPTCHA, they cannot be solved by those who rely on a screen reader (because providing the solution as alternate text would defeat the purpose of the CAPTCHA). Therefore, it is recommended to implement BotBlock as non-intrusively as possible. For example, you may wish to program your web application to only present a CAPTCHA to users during periods of elevated usage or submissions. This may result in a small amount of spam being able to sneak through before BotBlock kicks in, but will provide a smoother and more-accessible experience for all of your users the majority of the time, while still keeping you protected from the damage that large amounts of spam can cause.Please remember that BotBlock is a free, open source, community project. It makes no guarantees and provides no professional support. If you find it useful for mitigating spam and providing an additional layer of defense for your project, great! You are more than welcome to use it! But know that in these modern times with rapidly-improving AI and OCR technology, it is not completely implausible that BotBlock is, or eventually will be, defeatable. In addition, please keep in mind that BotBlock is self-hosted, and therefore will not be able to defend against traditional Denial of Service attacks. In fact, BotBlock could actually make those types of attacks more effective, due to the additional processing power required to generate CAPTCHAs. For the best results, it is recommended to only use BotBlock in line with the use cases outlined above.UsageThe full guide for developers on how to install, configure, and integrate BotBlock into their projects.InstallationThe easiest way to install BotBlock is to usepip:pipinstallbotblockOn some systems, you may need to run one of the following variations, instead:python-mpipinstallbotblockpip3installbotblockpython3-mpipinstallbotblockUsingpipto install BotBlock will automate compatibility checks and dependency downloads. However, if you elect to build BotBlock from source, or wish to clone our git repository and import BotBlock directly from there, here are the required dependencies and their corresponding versions:python>=3.9

cryptography>=39.0
importlib-resources>=5.12
Pillow>=9.4Generating a Simple CAPTCHATo generate a simple CAPTCHA using BotBlock, you must first import theCaptchaclass:frombotblock.captchaimportCaptchaNext, instantiate aCaptchaobject with the default settings:my_captcha=Captcha()Instantiating aCaptchaobject will also automatically generate a CAPTCHA.To save the CAPTCHA image for viewing, call thesavemethod on yourCaptchainstance, and supply the full path of the image file you would like to create. For example:my_captcha.save('/tmp/image.png')You can now open that image file with your favorite image viewer, to see the newly-generated CAPTCHA.To increase efficiency and make embedding CAPTCHAs within webpages as easy as possible, you can also call thebase64method on yourCaptchainstance to get its image data in base64 format, as a String:base64_captcha_image=my_captcha.base64()If the (shortened, for this example) base64 data returned wereRXhhbXBsZSBDQVBUQ0hBIEltYWdlIERhdGE=, you could embed it in a webpage using animgtag, like this:<imgsrc="data:image/png;base64,RXhhbXBsZSBDQVBUQ0hBIEltYWdlIERhdGE="alt="BotBlock CAPTCHA"/>Let's try it! Here's a short Python script you can run (interactively, if you'd like), that will generate a CAPTCHA and then embed it incaptcha.html: a blank webpage the script will create in the same directory that you run the script from. After running the script, you can double-click the file to view the webpage in your browser.Feel free to run this script a few times, reloading your web browser each time, to get a feel for the variety of CAPTCHAs BotBlock is capable of generating.frombotblock.captchaimportCaptchamy_captcha=Captcha()withopen('captcha.html','w')aswebpage:webpage.write('<!DOCTYPE html>\n<html>\n<head>')webpage.write('\n<title>BotBlock CAPTCHA Example</title>')webpage.write('\n</head>\n<body>\n<div>')webpage.write('\n<p>Embedded BotBlock CAPTCHA:</p>')webpage.write('\n<img src="data:image/png;base64,')webpage.write(my_captcha.base64())webpage.write('" alt="BotBlock CAPTCHA" />')webpage.write('\n</div>\n</body>\n</html>\n')To get a CAPTCHA's solution, you can call theget_solutionmethod on yourCaptchainstance, like so:solution=my_captcha.get_solution()Keep in mind that although the returned solution will always match the capitalization of the text appearing in the CAPTCHA image, you may not wish to enforce case sensitivity (and the BotBlock Engine will not enforce it by default) when verifying users' solutions.If you would like to see statistical information about aCaptchainstance, you can call itsprint_statsmethod, or useget_statsto return the same information as a dictionary:stats=my_captcha.get_stats()# To print the Captcha instance's stats, you can use either of the following:my_captcha.print_stats()print(my_captcha)Finally, thegeneratemethod can be called on yourCaptchainstance to regenerate its CAPTCHA image and metadata:my_captcha.generate()In most circumstances, developers should never need to call this method. For small projects, new CAPTCHAs should be created by simply instantiating a newCaptchaobject or using anEngineinstance. When you regenerate CAPTCHA data, all of the old data is lost, making it more complicated to fetch solutions and validate CAPTCHAs in the future. Thegeneratemethod is only provided for edge cases, because callinggeneratecan be slightly more efficient than instantiating a completely newCaptchaobject. That being said, if your code is generating enough CAPTCHAs for this tiny efficiency advantage to make a difference, then you should be using the (more efficient and robust)Engineobject to generate your CAPTCHAs, anyways.Using the CAPTCHA EngineBotBlock's CAPTCHA Engine provides all of the backend code needed to generate and validate CAPTCHAs in a production environment. For the vast majority of users, anEngineobject is a much better option than manually generating and validating CAPTCHAs via aCaptchaobject.Captchaobjects should really only be used for quick testing and unconventional use cases.Although theEngineobject's lack of certain features provided byCaptchaobjects may feel cumbersome at first, this is an intentional decision designed to increase security and efficiency, and reduce critical implementation errors. For example, when using the CAPTCHA Engine, you will not be able to programmatically view the correct solutions to generated CAPTCHAs. This ensures that the Engine's validation function must always be called, where strong encryption, replay attack protection, and CAPTCHA expiration is always used.When you instantiate anEngineobject, three subprocesses are automatically created. The first subprocess instantiates a pool ofCaptchainstances, creating a buffer capable of withstanding bursts in CAPTCHA requests. In the event that CAPTCHA settings are changed, this subprocess is the one responsible for updating all of theCaptchainstances with the new settings. The second subprocess handles the automatic regeneration of usedCaptchainstances, ensuring that the pool of fresh CAPTCHAs is always full. The third subprocess handles CAPTCHA validation, automatically checking CAPTCHAs submitted for validation to ensure that they haven't already been validated (preventing replay attacks). This subprocess also maintains the storage of validated CAPTCHAs, and automatically removes their data after they have expired.To use BotBlock's CAPTCHA Engine, you must first import theEngineclass, like so:frombotblock.captchaimportEngineAfter importing theEngineclass, you can instantiate anEngineobject with the default settings:engine=Engine()When using a CAPTCHA Engine, it's important to make sure that only oneEngineobject is instantiated per usage domain. Among other things, this helps to prevent inaccuracies that could arise from attempting to validate a CAPTCHA response with a differentEngineinstance than the one that generated the original CAPTCHA data. OneEngineinstance should be more than enough for most websites/projects. However, if you have isolated code that you think could benefit from having distinct CAPTCHA Engines (such as separateappswithin a Djangoproject), then instantiating more than one CAPTCHA Engine may be appropriate.When you are finished using anEngineinstance, that instancemustbe shut down. This will properly flush all of the buffers, clear all of the queues, allow the used memory to be freed, and terminate the various threads and processes started by the instance. To shut down anEngineinstance, simply call itsshut_downmethod:engine.shut_down()Theshut_downmethod will block until theEngineinstance has finished shutting down. This shouldn't take more than a few seconds at most.Alternatively, you can use awithstatement with anEngineinstance to automatically shut it down after the statement body finishes executing:withEngine()asengine:captcha=engine.get_captcha()To check if anEngineinstance has been shut down, you can call itsis_shut_downmethod:ifengine.is_shut_down():print('This Engine instance has been shut down.')else:print('This Engine instance is still active.')To get a fresh CAPTCHA from anEngineinstance, you can call itsget_captchamethod. This method will return a dictionary containing the base64-encoded CAPTCHA image as a String, and a URL-safe encrypted blob with the CAPTCHA's solution and provision time (the latter unencrypted but integrity-checked) as a String. You may optionally provide the full path to an image file as an argument to this method, to save (by creating or overwriting) the CAPTCHA image to that file. Here are some examples of getting CAPTCHAs from anEngineinstance:# Gets CAPTCHA data:first_captcha=engine.get_captcha()# Gets CAPTCHA data and saves CAPTCHA image to the specified file:second_captcha=engine.get_captcha('/tmp/captcha2.png')# Gets CAPTCHA data and then prints all of it:third_captcha=engine.get_captcha()print('Base64-Encoded CAPTCHA Image Data:')print(third_captcha['base64_captcha'])print('Encrypted Blob with CAPTCHA Authentication Data:')print(third_captcha['encrypted_blob'])For maximum efficiency, it is recommended to directly embed the CAPTCHA, as a base64-encoded image, into the webpage (or whatever other front-end you are using) that gets served to your users, rather than saving the CAPTCHA as an image file. See theGenerating a Simple CAPTCHAsection for examples of how to do this.When serving the CAPTCHA to your users, you will want to serve them the encrypted blob as well. The encrypted blob contains the authentication data necessary to validate a user's response. Don't worry, this data is completely safe to share with a user alongside the CAPTCHA image. The advantage of doing so, is that it prevents the developer from having to keep track of individual sessions and their associated CAPTCHA data, and allows theEngineinstance to immediately recycle theCaptchainstance that was used to generate the CAPTCHA data (as the encrypted blob now contains all of the data that will be needed during the validation phase). This dramatically increases efficiency.For those interested in the technical details, the blob is encrypted with AES in CBC mode, using a 128-bit key, PKCS7 for padding, and a SHA256 HMAC for authentication. It uses a strong, randomly-generated symmetric key, and is single-use only. The encryption is implemented using the battle-testedcryptography.fernetlibrary in Python.Although you aren't required to serve the encrypted blob to your users, and are welcome to write your own backend to associate encrypted blobs with users' CAPTCHA solutions, this is highly discouraged, and only opens the door to unnecessary mistakes, errors, and added overhead. The recommended method to serve this data to your users, if using BotBlock with a web application, is to include the encrypted blob as a hidden field within the same form that contains a user's proposed CAPTCHA solution. This ensures that you can efficiently distribute and receive the proposed CAPTCHA solution and associated authentication data, in unison. Most web application frameworks make frequent use of hidden form fields (such as for serving Cross Site Request Forgery Tokens), and include built-in methods that can easily be called from within a template to render a field as hidden.Once you receive a proposed solution and the associated authentication data from a user (after they submit a BotBlock-protected form on your website, for example), you can move on to validating their solution:encrypted_blob=get_authentication_data()# Made up function used for the exampleproposed_solution=get_proposed_solution()# Made up function used for the exampleifengine.validate(encrypted_blob,proposed_solution):return"Successfully solved the CAPTCHA"else:return"Failed to successfully solve the CAPTCHA"AnEngineinstance'svalidatemethod will always returnFalse, unless:The authentication data can be successfully decryptedThe authentication data isn't older than the CAPTCHA's lifetime (the CAPTCHA isn't expired)The proposed solution matches the correct solutionValidation hasn't already been attempted (successfully or unsuccessfully) with this encrypted blobFinally, to get statistical information about anEngineinstance, you can call itsget_statsmethod, to have the data returned as a dictionary. Alternatively, you can callprint_stats, to have the information printed to your terminal. It's important to note that for the few seconds (though usually less) that it takes anEngineinstance to compile the statistics, you may notice degraded query response speeds. Here's example output from callingprint_statson a productionEngineinstance:>>> engine.print_stats()
BOTBLOCK ENGINE INSTANCE

    Shut Down: No
    Active: 0 days, 16 hours, 21 minutes, and 30 seconds

    Pool Size: 500
    Fresh CAPTCHAs in Pool: 493
    Used CAPTCHAs in Pool: 7

    CAPTCHAs Distributed: 19630
    Validation Attempts: 12442
    CAPTCHA Solves: 10596

    CAPTCHAs Generated per Hour: 1200.0
    Validation Attempts per Hour: 760.59
    CAPTCHA Solves per Hour: 647.74

    Average Stats per Captcha Instance (500 Analyzed):
        Average number of CAPTCHAs generated per Captcha Instance: 39.26
        Average Font Size per Character per CAPTCHA: 122.35
        Average Number of Character Colors Evaluated per CAPTCHA: 28.31
        Average Number of Corrections to Character Positions per CAPTCHA: 1.54
        Average Image Data Size (In Bytes) per CAPTCHA: 30784.54
        Average Number of Layers of Noise Applied to Each CAPTCHA: 18.86

    Settings:
        WIDTH                                 = 750
        HEIGHT                                = 250
        FORMAT                                = 'PNG'
        TEXT                                  = ''
        TEXT_LENGTH                           = 6
        CHARACTER_SET                         = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'
        FONTS                                 = [
                                                    'Amatic-Bold.ttf',
                                                    'LifeSavers-Bold.ttf',
                                                    'TungusFont_Tinet.ttf',
                                                ]
        CHARACTER_HORIZONTAL_SHIFT_PERCENTAGE = 65
        CHARACTER_VERTICAL_SHIFT_PERCENTAGE   = 65
        FONT_SIZE_SHIFT_PERCENTAGE            = 25
        CHARACTER_OVERLAP_ENABLED             = False
        MAXIMUM_NOISE                         = 25
        MINIMUM_COLOR_BRIGHTNESS_DIFFERENCE   = 65
        MINIMUM_COLOR_HUE_DIFFERENCE          = 250
        CASE_SENSITIVE                        = False
        LIFETIME                              = 600
        POOL_SIZE                             = 500
        RATE_LIMIT                            = 0Customizing CAPTCHA SettingsNow that you can successfully generate and validate CAPTCHAs, it's time to learn how to customize them!All of the settings used to generate CAPTCHAs and configure an Engine are stored within an instance of theSettingsclass. This class provides some important functionality, such as:Validating provided settingsUsing provided settings to pre-compute "behind-the-scenes" values needed during CAPTCHA generationAllowing existing settings to be easily viewed, exported, or updatedBenchmarking different settings to provide an easy efficiency comparisonTo use custom settings, theSettingsclass must first be imported, like so:frombotblock.captchaimportSettingsNow that theSettingsclass has been imported, you can instantiate aSettingsobject:default_settings=Settings()Because we didn't provide any arguments to theSettingsobject during instantiation, this instance will have the default settings values.To view the current values that aSettingsinstance holds, you can call itsprint_settingsmethod, or just print the instance itself:default_settings.print_settings()print(default_settings)To retrieve the current settings as a dictionary, instead of printing them, you can use theget_settingsmethod:settings_dict=default_settings.get_settings()If you would like to compare a customizedSettingsinstance's values to the default values, you can call theprint_default_settingsandget_default_settingsmethods, which function just like their respectiveprint_settingsandget_settingsmethods, as outlined above.ifdefault_settings.get_settings()==default_settings.get_default_settings():print('The current settings instance contains the default settings.')else:print('The current settings instance has been customized.')To create aSettingsinstance with customized values, simply pass the settings you would like to customize and their new values as arguments upon instantiation. Any setting not specified with a custom value during instantiation will automatically use its default value.custom_settings=Settings(WIDTH=825,HEIGHT=275)You can also update the value of one or more settings after aSettingsobject has been instantiated, by calling itssetmethod. Any settings not specified with a new value will maintain the value they had before thesetmethod was called.# You can call `get_supported_image_formats` for a list of the supported image formats:new_image_format=custom_settings.get_supported_image_formats()[1]custom_settings.set(TEXT_LENGTH=8,CASE_SENSITIVE=True,FORMAT=new_image_format)Every time you make an update to the settings, all values are automatically revalidated, and any pre-computed values are recomputed. That being said, if something goes wrong, you can always manually call the validation method (validate_settings) yourself, or reset yourSettingsinstance back to the default values, with theset_default_valuesmethod:custom_settings.set_default_values()custom_settings.validate_settings()# Redundant; will raise an exception if invalid settings foundWhenever aCaptchaorEngineobject is instantiated without any arguments, it will create its ownSettingsinstance with the default values. To have aCaptchaorEngineinstance use custom settings, you must provide a customSettingsobject as an argument upon instantiation, or as an argument to theupdate_settingsmethod:frombotblock.captchaimport*custom_settings=Settings(WIDTH=675,HEIGHT=225)custom_engine=Engine(custom_settings)custom_captcha=Captcha()custom_engine.update_settings(Settings(FORMAT='GIF'))# You can use the `get_settings` method to get the current `Settings` object:captcha_settings=custom_captcha.get_settings()captcha_settings.set(FORMAT='JPEG')custom_captcha.update_settings(captcha_settings)# Provide no `Settings` instance as an argument, to restore the default settings:custom_engine.update_settings()Modifying settings can have a big impact on efficiency. For example, decreasing the length of the CAPTCHA text can make CAPTCHA generation significantly faster. However, this also decreases security by exponentially raising the odds of randomly guessing the correct solution to a CAPTCHA (which is a big deal, when automated guessing is taken into account). Therefore, theSettingsclass comes with a built-in benchmarking method, to help you calculate the efficiency tradeoff for customized settings, and determine which settings are the best for your project.To run an efficiency benchmark, simply instantiate aSettingsobject with your desired settings, then call itscompare_efficiencymethod. You can pass anotherSettingsinstance to this method to compare against a second set of customized settings, or leave it empty to compare against the default settings. You may also modify the default benchmarking time of 5 minutes (300 seconds).first_settings=Settings(TEXT_LENGTH=10)second_settings=Settings(TEXT_LENGTH=5)first_settings.compare_efficiency(second_settings)first_settings.compare_efficiency(settings=Settings(TEXT_LENGTH=3),test_length=120)When running a benchmark, please keep in mind that:The specified test length is a rough target, and not an exact value. The final test length may end up being a bit above or below this value, depending on how long the scheduled benchmarks end up taking.The benchmark is not guaranteed to be 100% accurate. Due to a variety of factors (such as background tasks that the OS may randomly start/stop during the benchmark), you should expect each benchmark to return a slightly different result.To get the best results, it is recommended to run the benchmark a few times, and make sure not to use short test lengths. If, after doing so, you get consistent results (i.e. oneSettingsinstance is always found to me more efficient than the other), then you can feel much more confident about the accuracy of those results.The raw numbers shown (such as the number of CAPTCHAs generated and the amount of time they were generated in) are not indicative of the performance you can expect when using an Engine, as the benchmark only utilizesCaptchaobjects for increased simplicity and accuracy (and for that reason, customized Engine-specific settings will not impact the benchmark). That being said, though the raw numbers may not apply, the relative efficiency percentages betweenSettingsinstances should still be accurate forEngineobjects.If you have a low-to-medium traffic website, the efficiency of your settings may not matter all that much, as you won't need to generate tens of thousands of CAPTCHAs per minute anyways. Therefore, don't get too hung up on the efficiency of your CAPTCHA Engine, and instead focus more on choosing the best, and most-accessible settings for your site.Available SettingsThis section serves as a reference for each available setting that a developer may customize.WIDTHApplies To:CAPTCHAsDefault Value:750Must Be:Of typeintGreater in value than9Greater or equal in value to theHEIGHTsetting's valueEfficiency Impact:In general, the greater the value, the lesser the efficiencyDescription:Sets the width of the CAPTCHA image to generate, in pixelsHEIGHTApplies To:CAPTCHAsDefault Value:250Must Be:Of typeintGreater in value than4Lesser or equal in value to theWIDTHsetting's valueEfficiency Impact:In general, the greater the value, the lesser the efficiencyDescription:Sets the height of the CAPTCHA image to generate, in pixelsFORMATApplies To:CAPTCHAsDefault Value:'PNG'Must Be:Of typestrEqual to one of the following values:'BMP''GIF''ICO''JPEG''PNG''TIFF''WEBP''PDF'Efficiency Impact:Image formats in order of average generation speed (from quickest to slowest):JPEGPDFBMPTIFFPNGICOWEBPGIFImage formats in order of average file size (from smallest to largest):GIFICOWEBPPNGJPEGPDFTIFFBMPNote: results may vary by systemDescription:Sets the image format of the generated CAPTCHA imageThe PNG and JPEG image formats are highly recommended due to their widespread support, quick generation speed, and relatively small file sizes.The PNG format was chosen as the default, due to it being a lossless image format. This ensures that the CAPTCHA details, including all of the noise, are clearly visible in the image. That being said, if you're using a large-enough image size for the text to still be clear, and don't mind compression artifacts on the image, then switching this setting from'PNG'to'JPEG'could just about double the CAPTCHA generation efficiency, while maintaining about the same file sizes.TEXTApplies To:CAPTCHAsDefault Value:''Must Be:Of typestrEmpty, or greater in length than2Efficiency Impact:In general, the greater the length, the lesser the efficiencyDescription:Sets custom CAPTCHA text to useWhen blank, CAPTCHA text will be randomly generated using characters from theCHARACTER_SETsetting. Otherwise, CAPTCHA text (and therefore the solution) will always be equal to this value (negating theCHARACTER_SETandTEXT_LENGTHsettings).TEXT_LENGTHApplies To:CAPTCHAsDefault Value:6Must Be:Of typeintGreater in value than2Efficiency Impact:In general, the lesser the value, the greater the efficiencyDescription:Sets the length of randomly-generated CAPTCHA text/solutionsBe sure not to set the text length too low, as each fewer character is an exponential decrease in the number of possible CAPTCHA solutions. If the number of possible solutions gets too low, say10,000, then a malicious user could write code to automatically submit a form10,000,000times, with a random guess of the solution each time, and expect about1,000of those submissions to be excepted as valid.Using the default character set with case sensitivity disabled (also the default), this is how many possible solutions there are for the first tenTEXT_LENGTHvalues:TEXT_LENGTHSolutions1312961329,7914923,521528,629,1516887,503,681727,512,614,1118852,891,037,441926,439,622,160,67110819,628,286,980,801The font size used when generating a CAPTCHA is automatically calculated based on the text length and the image size. The greater the text length set here, the smaller the font size will be.CHARACTER_SETApplies To:CAPTCHAsDefault Value:'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'Must Be:Of typestrGreater in length than0when theTEXTsetting is blankComprised of unique charactersEfficiency Impact:Longer character sets are slightly more efficient than shorter onesDescription:Sets the character set from which random characters are chosen for the CAPTCHA text, when no custom text is provided via theTEXTsettingWhen designing a custom character set, you should keep the following in mind:The character set should be relatively large (even with case sensitivity disabled), in order to increase bruteforce resistanceThe character set should still include mixed-case characters (if applicable) when case sensitivity is disabled, to increase the variability of CAPTCHA imagesThe character set should only include characters that are easily-recognizable for your usersThe character set should not contain any characters that aren't commonly found on the keyboards of your users, or that they don't commonly typeThe character set should not contain any characters that look identical or very similar when rendered in any of the CAPTCHA's fonts (for example,I,l, and1)The character set should not contain any characters that Python doesn't know how to properly iterate overFONTSApplies To:CAPTCHAsDefault Value:['Amatic-Bold.ttf', 'LifeSavers-Bold.ttf', 'TungusFont_Tinet.ttf']Must Be:Of typelistand containing one or morestrtypes, which represent paths to valid font filesEfficiency Impact:Variable, based on the typeface(s) providedDescription:Sets the fonts that are chosen at random to render each character in the CAPTCHA imageIf changing this setting, make sure to test each font with your character set, to ensure that the font can render all of the characters, and that no two characters look the same when rendered with any combination of the fonts. You may also wish to keep in mind that the more unique the font, the greater the chance that OCR/AI technologies will be unable to read it.Note: the default fonts, while all open source, do not fall under this repository's MIT license. Navigate to thefontsdirectory in this repository to view each font's license.CHARACTER_HORIZONTAL_SHIFT_PERCENTAGEApplies To:CAPTCHAsDefault Value:65Must Be:Of typeintA whole number less than101in valueEfficiency Impact:NegligibleDescription:Sets the maximum percentage to horizontally shift charactersDuring CAPTCHA generation, characters' locations are shifted horizontally by a random percentage of their containing box's width. The maximum percentage that a character may be shifted left or right is determined by this setting.CHARACTER_VERTICAL_SHIFT_PERCENTAGEApplies To:CAPTCHAsDefault Value:65Must Be:Of typeintA whole number less than101in valueEfficiency Impact:NegligibleDescription:Sets the maximum percentage to vertically shift charactersDuring CAPTCHA generation, characters' locations are shifted vertically by a random percentage of the containing box's height. The maximum percentage that a character may be shifted up or down is determined by this setting.FONT_SIZE_SHIFT_PERCENTAGEApplies To:CAPTCHAsDefault Value:25Must Be:Of typeintA whole number less than101in valueEfficiency Impact:NegligibleDescription:Sets the maximum percentage to shift characters' font sizesDuring CAPTCHA generation, characters' font sizes are shifted by a random percentage of their (automatically calculated) default size. The maximum percentage that a character's font size may be increased or decreased is determined by this setting.CHARACTER_OVERLAP_ENABLEDApplies To:CAPTCHAsDefault Value:FalseMust Be:Of typeboolEfficiency Impact:In general, when set toTrue, CAPTCHA generation is more efficientDescription:WhenFalse, the randomly-shifted character positions in the CAPTCHA are checked and modified as necessary, to ensure that two characters never overlap, characters don't get positioned outside of the image border, and characters are always presented in the correct order. WhenTrue, this check is skipped, and character positions are only roughly enforced. This can lead to some CAPTCHAs containing overlapping characters, characters that are cut off (partially or completely) by the edge of the image, and/or characters that are slightly out of order. This is only a significant risk when one or both of theCHARACTER_HORIZONTAL_SHIFT_PERCENTAGEandCHARACTER_VERTICAL_SHIFT_PERCENTAGEsettings' values are high.MAXIMUM_NOISEApplies To:CAPTCHAsDefault Value:25Must Be:Of typeintA whole numberEfficiency Impact:In general, the greater the value, the lesser the efficiencyDescription:Sets the maximum number of layers of noise to apply to a CAPTCHAWhen CAPTCHAs are generated, a random number of layers of noise (from zero to this setting's value, inclusive) is applied to the image, to help obscure the text. Each layer of noise is randomly chosen to be an arc, line, or points drawn over the image at random locations or in random quantities.MINIMUM_COLOR_BRIGHTNESS_DIFFERENCEApplies To:CAPTCHAsDefault Value:65Must Be:Of typeintLess than201in valueEfficiency Impact:In general, the greater the value, the lesser the efficiencyDescription:Sets the minimum color brightness difference between the CAPTCHA background color and the CAPTCHA text colorWhen CAPTCHAs are generated, their background color and the color of each character is chosen at random. After a character's color is selected, however, the brightness difference between it and the background color is evaluated. If the brightness difference is less than the minimum value set by this setting, a new character color is chosen. This process repeats until a compliant character color is found. If, after 10,000 tries, a compliant character color cannot be found, a new, random background color for the CAPTCHA is chosen, and the process starts all over again.The default value of this setting (combined with the default value of theMINIMUM_COLOR_HUE_DIFFERENCEsetting) should be large enough to ensure that character colors with a high-enough contrast to the background color, for most people, are selected, but low enough to keep the impact on efficiency negligible.While this setting's default value may be good for testing,it should be changed when using BotBlock in production. W3 recommends setting this value to at least125, to ensure compliance with web accessibility standards.MINIMUM_COLOR_HUE_DIFFERENCEApplies To:CAPTCHAsDefault Value:250Must Be:Of typeintLess than601in valueEfficiency Impact:In general, the greater the value, the lesser the efficiencyDescription:Sets the minimum color hue difference between the CAPTCHA background color and the CAPTCHA text colorWhen CAPTCHAs are generated, their background color and the color of each character is chosen at random. After a character's color is selected, however, the hue difference between it and the background color is evaluated. If the hue difference is less than the minimum value set by this setting, a new character color is chosen. This process repeats until a compliant character color is found. If, after 10,000 tries, a compliant character color cannot be found, a new, random background color for the CAPTCHA is chosen, and the process starts all over again.The default value of this setting (combined with the default value of theMINIMUM_COLOR_BRIGHTNESS_DIFFERENCEsetting) should be large enough to ensure that character colors with a high-enough contrast to the background color, for most people, are selected, but low enough to keep the impact on efficiency negligible.While this setting's default value may be good for testing,it should be changed when using BotBlock in production. W3 recommends setting this value to at least500, to ensure compliance with web accessibility standards.CASE_SENSITIVEApplies To:EnginesDefault Value:FalseMust Be:Of typeboolEfficiency Impact:NegligibleDescription:WhenTrue, provided solutions must match the case (uppercase or lowercase) of the CAPTCHA text in order for the Engine'svalidatemethod to conclude that the solution is valid. For example:CAPTCHA TextUser's SolutionConsidered ValidNfBnhBNfBnhBTrueCSKteHcsktehFalseFSv52hFSV52HFalseTav3dHTaV3dHFalseWhenFalse, the Engine'svalidatemethod will determine that a solution is valid as long as the correct characters are provided in the correct order, regardless of their capitalization. For example:CAPTCHA TextUser's SolutionConsidered ValidNfBnhBNfBnhBTrueCSKteHcsktehTrueFSv52hFSV52HTrueTav3dHTaV3dHTrueIt is highly recommended to use the default value ofFalsefor this setting, even if it makes the CAPTCHA easier to bruteforce. Enabling case sensitivity can be very frustrating for users who may not be expecting case sensitivity, or who may have trouble distinguishing the random case of each character (especially when a variety of fonts and/or shifts are used).It should also be noted that when this setting is set toFalse, Python'sstr.lowermethod is applied to the CAPTCHA text and the proposed solution during validation, which may not work properly on all possible character sets. In those situations, you may need to change this setting toTrue.###06597ba1cfc49461462bfd3896895253a067ddf2 LIFETIMEApplies To:EnginesDefault Value:600Must Be:Of typeintA whole numberEfficiency Impact:Negligible in most use casesDescription:Sets the lifetime (in seconds) of CAPTCHAs, after which they expireAny CAPTCHAs passed to an Engine for validation after the number of seconds indicated by this setting have passed since the CAPTCHA was created, will be declared as invalid. The default value for this setting is600seconds, or ten minutes, but any time between30seconds and1800seconds (30 minutes) is reasonable. If your website/project has a high level of traffic, you may wish to consider keeping the setting's value on the smaller side, to increase memory and validation efficiency.POOL_SIZEApplies To:EnginesDefault Value:500Must Be:Of typeintA natural numberEfficiency Impact:Variable, depending on query rate and variance, host system specifications, and moreDescription:Sets an Engine's freshCaptchainstance pool sizeIn order to increase efficiency and query response speeds, and allow for burstable performance, Engine objects create and maintain a pool of freshCaptchainstances, with CAPTCHA images and data ready to be distributed at any moment. This size of this pool can be tuned to fit your website/project's requirements. For example, if your website often experiences large bursts in traffic, you may wish to increase thePOOL_SIZEsetting's value. On the other hand, if running on a system with very limited memory, you may wish to decrease this setting's value.Note: this is the only setting that cannot be dynamically updated.RATE_LIMITApplies To:EnginesDefault Value:0Must Be:Of typeintA whole numberOROf typefloatGreater in value than0.0Efficiency Impact:No impact on CAPTCHA generation efficiency when disabled (default), very slight impact when enabledThe lesser the integer value (still greater than0), the lower the average CPU usage by BotBlockThe greater the floating point value, the lower the average CPU usage by BotBlockDescription:Limits the number of CAPTCHAs that may be generated per minuteFor systems with strict limits on average CPU usage, this setting allows the developer to limit the number of CAPTCHAs that BotBlock will generate per minute, via one of two ways:When an integer value is supplied (e.g.250), BotBlock will only allow that number of CAPTCHAs to be generate per minute. If the limit is reached within one minute, BotBlock will pause CAPTCHA generation until the next minute starts.When a floating point value is supplied (e.g.0.1), BotBlock will sleep for that number of seconds after each CAPTCHA that it generates, before beginning to generate the next CAPTCHA.All rate limiting can be disabled by making this setting's value equal to0.Note: the rate limiting does not apply to the initial CAPTCHA generation (to fill the pool) that occurs when anEngineis first instantiated. It will also not apply to the regeneration that occurs when anEngineinstance's settings are updated.Example CAPTCHAsHere are some example CAPTCHAs with different settings enabled, so you can get a feel for what some of the main settings do. Many of these are using exaggerated settings that wouldn't actually be used in a production environment.CAPTCHAs generated using the default settings:CAPTCHAs generated with default settings and saved as JPEGs:CAPTCHAs generated with higher contrast and low noise:CAPTCHAs generated with high noise and character overlap enabled:CAPTCHAs of various sizes and text lengths: