botblock


Namebotblock JSON
Version 2.1.0 PyPI version JSON
download
home_page
SummaryA modern, self-hosted, privacy-respecting, CAPTCHA solution
upload_time2023-03-25 02:50:06
maintainer
docs_urlNone
author
requires_python>=3.9
licenseMIT License Copyright (c) 2023 Priveasy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords botblock bot-block bot block captcha spam protect form website self-hosted self hosted privacy priveasy p5vc
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # BotBlock

***A modern, self-hosted, privacy-respecting, CAPTCHA solution***

------------

# Table of Contents

- [Overview](#overview "Overview")
- [Implementation Details](#implementation-details "Implementation Details")
- [Usage](#usage "Usage")
  - [Installation](#installation "Installation")
  - [Generating a Simple CAPTCHA](#generating-a-simple-captcha "Generating a Simple CAPTCHA")
  - [Using the CAPTCHA Engine](#using-the-captcha-engine "Using the CAPTCHA Engine")
  - [Customizing CAPTCHA Settings](#customizing-captcha-settings "Customizing CAPTCHA Settings")
  - [Available Settings](#available-settings "Available Settings")
- [Example CAPTCHAs](#example-captchas "Example CAPTCHAs")

# Overview

BotBlock 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 Details

BotBlock 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.


# Usage

The full guide for developers on how to install, configure, and integrate BotBlock into their projects.

## Installation

The easiest way to install BotBlock is to use `pip`:

```bash
pip install botblock
```

On some systems, you may need to run one of the following variations, instead:

```bash
python -m pip install botblock
```

```bash
pip3 install botblock
```

```bash
python3 -m pip install botblock
```

Using `pip` to 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.4
```

## Generating a Simple CAPTCHA

To generate a simple CAPTCHA using BotBlock, you must first import the `Captcha` class:

```python
from botblock.captcha import Captcha
```

Next, instantiate a `Captcha` object with the default settings:

```python
my_captcha = Captcha()
```

Instantiating a `Captcha` object will also automatically generate a CAPTCHA.

To save the CAPTCHA image for viewing, call the `save` method on your `Captcha` instance, and supply the full path of the image file you would like to create. For example:

```python
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 the `base64` method on your `Captcha` instance to get its image data in base64 format, as a String:

```python
base64_captcha_image = my_captcha.base64()
```

If the (shortened, for this example) base64 data returned were `RXhhbXBsZSBDQVBUQ0hBIEltYWdlIERhdGE=`, you could embed it in a webpage using an `img` tag, like this:

```html
<img src="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 in `captcha.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.

```python
from botblock.captcha import Captcha

my_captcha = Captcha()

with open('captcha.html', 'w') as webpage:
	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 the `get_solution` method on your `Captcha` instance, like so:

```python
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 a `Captcha` instance, you can call its `print_stats` method, or use `get_stats` to return the same information as a dictionary:

```python
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, the `generate` method can be called on your `Captcha` instance to regenerate its CAPTCHA image and metadata:

```python
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 new `Captcha` object or using an `Engine` instance. 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. The `generate` method is only provided for edge cases, because calling `generate` can be slightly more efficient than instantiating a completely new `Captcha` object. 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) `Engine` object to generate your CAPTCHAs, anyways.

### Using the CAPTCHA Engine

BotBlock'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, an `Engine` object is a much better option than manually generating and validating CAPTCHAs via a `Captcha` object. `Captcha` objects should really only be used for quick testing and unconventional use cases.

Although the `Engine` object's lack of certain features provided by `Captcha` objects 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 an `Engine` object, three subprocesses are automatically created. The first subprocess instantiates a pool of `Captcha` instances, 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 the `Captcha` instances with the new settings. The second subprocess handles the automatic regeneration of used `Captcha` instances, 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 the `Engine` class, like so:

```python
from botblock.captcha import Engine
```

After importing the `Engine` class, you can instantiate an `Engine` object with the default settings:

```python
engine = Engine()
```

When using a CAPTCHA Engine, it's important to make sure that only one `Engine` object 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 different `Engine` instance than the one that generated the original CAPTCHA data. One `Engine` instance 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 separate *apps* within a Django *project*), then instantiating more than one CAPTCHA Engine may be appropriate.

When you are finished using an `Engine` instance, that instance ***must*** be 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 an `Engine` instance, simply call its `shut_down` method:

```python
engine.shut_down()
```

The `shut_down` method will block until the `Engine` instance has finished shutting down. This shouldn't take more than a few seconds at most.

Alternatively, you can use a `with` statement with an `Engine` instance to automatically shut it down after the statement body finishes executing:

```python
with Engine() as engine:
    captcha = engine.get_captcha()
```

To check if an `Engine` instance has been shut down, you can call its `is_shut_down` method:

```python
if engine.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 an `Engine` instance, you can call its `get_captcha` method. 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 an `Engine` instance:

```python
# 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 the [Generating a Simple CAPTCHA](#generating-a-simple-captcha "Generating a Simple CAPTCHA") section 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 the `Engine` instance to immediately recycle the `Captcha` instance 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-tested `cryptography.fernet` library 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:

```python
encrypted_blob = get_authentication_data() # Made up function used for the example
proposed_solution = get_proposed_solution() # Made up function used for the example
if engine.validate(encrypted_blob, proposed_solution):
	return "Successfully solved the CAPTCHA"
else:
	return "Failed to successfully solve the CAPTCHA"
```

An `Engine` instance's `validate` method will always return `False`, unless:

- The authentication data can be successfully decrypted
- The authentication data isn't older than the CAPTCHA's lifetime (the CAPTCHA isn't expired)
- The proposed solution matches the correct solution
- Validation hasn't already been attempted (successfully or unsuccessfully) with this encrypted blob

Finally, to get statistical information about an `Engine` instance, you can call its `get_stats` method, to have the data returned as a dictionary. Alternatively, you can call `print_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 an `Engine` instance to compile the statistics, you may notice degraded query response speeds. Here's example output from calling `print_stats` on a production `Engine` instance:

```
>>> 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                            = 0
```

## Customizing CAPTCHA Settings

Now 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 the `Settings` class. This class provides some important functionality, such as:

- Validating provided settings
- Using provided settings to pre-compute "behind-the-scenes" values needed during CAPTCHA generation
- Allowing existing settings to be easily viewed, exported, or updated
- Benchmarking different settings to provide an easy efficiency comparison

To use custom settings, the `Settings` class must first be imported, like so:

```python
from botblock.captcha import Settings
```

Now that the `Settings` class has been imported, you can instantiate a `Settings` object:

```python
default_settings = Settings()
```

Because we didn't provide any arguments to the `Settings` object during instantiation, this instance will have the default settings values.

To view the current values that a `Settings` instance holds, you can call its `print_settings` method, or just print the instance itself:

```python
default_settings.print_settings()
print(default_settings)
```

To retrieve the current settings as a dictionary, instead of printing them, you can use the `get_settings` method:

```python
settings_dict = default_settings.get_settings()
```

If you would like to compare a customized `Settings` instance's values to the default values, you can call the `print_default_settings` and `get_default_settings` methods, which function just like their respective `print_settings` and `get_settings` methods, as outlined above.

```python
if default_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 a `Settings` instance 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.

```python
custom_settings = Settings(WIDTH = 825, HEIGHT = 275)
```

You can also update the value of one or more settings after a `Settings` object has been instantiated, by calling its `set` method. Any settings not specified with a new value will maintain the value they had before the `set` method was called.

```python
# 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 your `Settings` instance back to the default values, with the `set_default_values` method:

```python
custom_settings.set_default_values()
custom_settings.validate_settings() # Redundant; will raise an exception if invalid settings found
```

Whenever a `Captcha` or `Engine` object is instantiated without any arguments, it will create its own `Settings` instance with the default values. To have a `Captcha` or `Engine` instance use custom settings, you must provide a custom `Settings` object as an argument upon instantiation, or as an argument to the `update_settings` method:

```python
from botblock.captcha import *

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, the `Settings` class 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 a `Settings` object with your desired settings, then call its `compare_efficiency` method. You can pass another `Settings` instance 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).

```python
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. one `Settings` instance 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 utilizes `Captcha` objects 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 between `Settings` instances should still be accurate for `Engine` objects.
- 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 Settings

This section serves as a reference for each available setting that a developer may customize.

### WIDTH

**Applies To:** CAPTCHAs

**Default Value:** `750`

**Must Be:**

- Of type `int`
- Greater in value than `9`
- Greater or equal in value to the `HEIGHT` setting's value

**Efficiency Impact:**

In general, the greater the value, the lesser the efficiency

**Description:**

Sets the width of the CAPTCHA image to generate, in pixels

### HEIGHT

**Applies To:** CAPTCHAs

**Default Value:** `250`

**Must Be:**

- Of type `int`
- Greater in value than `4`
- Lesser or equal in value to the `WIDTH` setting's value

**Efficiency Impact:**

In general, the greater the value, the lesser the efficiency

**Description:**

Sets the height of the CAPTCHA image to generate, in pixels

### FORMAT

**Applies To:** CAPTCHAs

**Default Value:** `'PNG'`

**Must Be:**

- Of type `str`
- Equal 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):

- JPEG
- PDF
- BMP
- TIFF
- PNG
- ICO
- WEBP
- GIF

Image formats in order of average file size (from smallest to largest):

- GIF
- ICO
- WEBP
- PNG
- JPEG
- PDF
- TIFF
- BMP

*Note: results may vary by system*

**Description:**

Sets the image format of the generated CAPTCHA image

The 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.

### TEXT

**Applies To:** CAPTCHAs

**Default Value:** `''`

**Must Be:**

- Of type `str`
- Empty, or greater in length than `2`

**Efficiency Impact:**

In general, the greater the length, the lesser the efficiency

**Description:**

Sets custom CAPTCHA text to use

When blank, CAPTCHA text will be randomly generated using characters from the `CHARACTER_SET` setting. Otherwise, CAPTCHA text (and therefore the solution) will always be equal to this value (negating the `CHARACTER_SET` and `TEXT_LENGTH` settings).

### TEXT_LENGTH

**Applies To:** CAPTCHAs

**Default Value:** `6`

**Must Be:**

- Of type `int`
- Greater in value than `2`

**Efficiency Impact:**

In general, the lesser the value, the greater the efficiency

**Description:**

Sets the length of randomly-generated CAPTCHA text/solutions

Be 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, say `10,000`, then a malicious user could write code to automatically submit a form `10,000,000` times, with a random guess of the solution each time, and expect about `1,000` of 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 ten `TEXT_LENGTH` values:

| TEXT_LENGTH |      Solutions      |
|-------------|---------------------|
|      1      |                  31 |
|      2      |                 961 |
|      3      |              29,791 |
|      4      |             923,521 |
|      5      |          28,629,151 |
|      6      |         887,503,681 |
|      7      |      27,512,614,111 |
|      8      |     852,891,037,441 |
|      9      |  26,439,622,160,671 |
|     10      | 819,628,286,980,801 |

The 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_SET

**Applies To:** CAPTCHAs

**Default Value:** `'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'`

**Must Be:**

- Of type `str`
- Greater in length than `0` when the `TEXT` setting is blank
- Comprised of unique characters

**Efficiency Impact:**

Longer character sets are slightly more efficient than shorter ones

**Description:**

Sets the character set from which random characters are chosen for the CAPTCHA text, when no custom text is provided via the `TEXT` setting

When 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 resistance
- The character set should still include mixed-case characters (if applicable) when case sensitivity is disabled, to increase the variability of CAPTCHA images
- The character set should only include characters that are easily-recognizable for your users
- The character set should not contain any characters that aren't commonly found on the keyboards of your users, or that they don't commonly type
- The 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`, and `1`)
- The character set should not contain any characters that Python doesn't know how to properly iterate over

### FONTS

**Applies To:** CAPTCHAs

**Default Value:** `['Amatic-Bold.ttf', 'LifeSavers-Bold.ttf', 'TungusFont_Tinet.ttf']`

**Must Be:**

- Of type `list` and containing one or more `str` types, which represent paths to valid font files

**Efficiency Impact:**

Variable, based on the typeface(s) provided

**Description:**

Sets the fonts that are chosen at random to render each character in the CAPTCHA image

If 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 the `fonts` directory in this repository to view each font's license.*

### CHARACTER_HORIZONTAL_SHIFT_PERCENTAGE

**Applies To:** CAPTCHAs

**Default Value:** `65`

**Must Be:**

- Of type `int`
- A whole number less than `101` in value

**Efficiency Impact:**

Negligible

**Description:**

Sets the maximum percentage to horizontally shift characters

During 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_PERCENTAGE

**Applies To:** CAPTCHAs

**Default Value:** `65`

**Must Be:**

- Of type `int`
- A whole number less than `101` in value

**Efficiency Impact:**

Negligible

**Description:**

Sets the maximum percentage to vertically shift characters

During 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_PERCENTAGE

**Applies To:** CAPTCHAs

**Default Value:** `25`

**Must Be:**

- Of type `int`
- A whole number less than `101` in value

**Efficiency Impact:**

Negligible

**Description:**

Sets the maximum percentage to shift characters' font sizes

During 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_ENABLED

**Applies To:** CAPTCHAs

**Default Value:** `False`

**Must Be:**

- Of type `bool`

**Efficiency Impact:**

In general, when set to `True`, CAPTCHA generation is more efficient

**Description:**

When `False`, 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. When `True`, 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 the `CHARACTER_HORIZONTAL_SHIFT_PERCENTAGE` and `CHARACTER_VERTICAL_SHIFT_PERCENTAGE` settings' values are high.

### MAXIMUM_NOISE

**Applies To:** CAPTCHAs

**Default Value:** `25`

**Must Be:**

- Of type `int`
- A whole number

**Efficiency Impact:**

In general, the greater the value, the lesser the efficiency

**Description:**

Sets the maximum number of layers of noise to apply to a CAPTCHA

When 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_DIFFERENCE

**Applies To:** CAPTCHAs

**Default Value:** `65`

**Must Be:**

- Of type `int`
- Less than `201` in value

**Efficiency Impact:**

In general, the greater the value, the lesser the efficiency

**Description:**

Sets the minimum color brightness difference between the CAPTCHA background color and the CAPTCHA text color

When 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 the `MINIMUM_COLOR_HUE_DIFFERENCE` setting) 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 least `125`, to ensure compliance with web accessibility standards.

### MINIMUM_COLOR_HUE_DIFFERENCE

**Applies To:** CAPTCHAs

**Default Value:** `250`

**Must Be:**

- Of type `int`
- Less than `601` in value

**Efficiency Impact:**

In general, the greater the value, the lesser the efficiency

**Description:**

Sets the minimum color hue difference between the CAPTCHA background color and the CAPTCHA text color

When 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 the `MINIMUM_COLOR_BRIGHTNESS_DIFFERENCE` setting) 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 least `500`, to ensure compliance with web accessibility standards.

### CASE_SENSITIVE

**Applies To:** Engines

**Default Value:** `False`

**Must Be:**

- Of type `bool`

**Efficiency Impact:**

Negligible

**Description:**

When `True`, provided solutions must match the case (uppercase or lowercase) of the CAPTCHA text in order for the Engine's `validate` method to conclude that the solution is valid. For example:

| CAPTCHA Text | User's Solution | Considered Valid |
|--------------|-----------------|------------------|
|    NfBnhB    |      NfBnhB     |       True       |
|    CSKteH    |      cskteh     |       False      |
|    FSv52h    |      FSV52H     |       False      |
|    Tav3dH    |      TaV3dH     |       False      |

When `False`, the Engine's `validate` method 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 Text | User's Solution | Considered Valid |
|--------------|-----------------|------------------|
|    NfBnhB    |      NfBnhB     |       True       |
|    CSKteH    |      cskteh     |       True       |
|    FSv52h    |      FSV52H     |       True       |
|    Tav3dH    |      TaV3dH     |       True       |

It is highly recommended to use the default value of `False` for 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 to `False`, Python's `str.lower` method 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 to `True`.

###06597ba1cfc49461462bfd3896895253a067ddf2 LIFETIME

**Applies To:** Engines

**Default Value:** `600`

**Must Be:**

- Of type `int`
- A whole number

**Efficiency Impact:**

Negligible in most use cases

**Description:**

Sets the lifetime (in seconds) of CAPTCHAs, after which they expire

Any 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 is `600` seconds, or ten minutes, but any time between `30` seconds and `1800` seconds (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_SIZE

**Applies To:** Engines

**Default Value:** `500`

**Must Be:**

- Of type `int`
- A natural number

**Efficiency Impact:**

Variable, depending on query rate and variance, host system specifications, and more

**Description:**

Sets an Engine's fresh `Captcha` instance pool size

In order to increase efficiency and query response speeds, and allow for burstable performance, Engine objects create and maintain a pool of fresh `Captcha` instances, 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 the `POOL_SIZE` setting'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_LIMIT

**Applies To:** Engines

**Default Value:** `0`

**Must Be:**

- Of type `int`
- A whole number

*OR*

- Of type `float`
- Greater in value than `0.0`

**Efficiency Impact:**

No impact on CAPTCHA generation efficiency when disabled (default), very slight impact when enabled

The lesser the integer value (still greater than `0`), the lower the average CPU usage by BotBlock

The greater the floating point value, the lower the average CPU usage by BotBlock

**Description:**

Limits the number of CAPTCHAs that may be generated per minute

For 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 to `0`.

Note: the rate limiting does not apply to the initial CAPTCHA generation (to fill the pool) that occurs when an `Engine` is first instantiated. It will also not apply to the regeneration that occurs when an `Engine` instance's settings are updated.

# Example CAPTCHAs

Here 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:

![First Example of a Default CAPTCHA](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-1.png)
![Second Example of a Default CAPTCHA](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-2.png)
![Third Example of a Default CAPTCHA](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-3.png)

### CAPTCHAs generated with default settings and saved as JPEGs:

![First Example of a Default CAPTCHA Saved as a JPEG](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-1.jpeg)
![Second Example of a Default CAPTCHA Saved as a JPEG](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-2.jpeg)
![Third Example of a Default CAPTCHA Saved as a JPEG](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-3.jpeg)

### CAPTCHAs generated with higher contrast and low noise:

![First Example of a CAPTCHA with Higher Contrast and Low Noise](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-contrast-low-noise-captcha-1.png)
![Second Example of a CAPTCHA with Higher Contrast and Low Noise](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-contrast-low-noise-captcha-2.png)
![Third Example of a CAPTCHA with Higher Contrast and Low Noise](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-contrast-low-noise-captcha-3.png)

### CAPTCHAs generated with high noise and character overlap enabled:

![First Example of a CAPTCHA with High Noise and Character Overlap](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-noise-character-overlap-captcha-1.png)
![Second Example of a CAPTCHA with High Noise and Character Overlap](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-noise-character-overlap-captcha-2.png)
![Third Example of a CAPTCHA with High Noise and Character Overlap](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-noise-character-overlap-captcha-3.png)

### CAPTCHAs of various sizes and text lengths:

![First Example of a CAPTCHA with a Random Size and Text Length](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/random-size-and-text-length-captcha-1.png)
![Second Example of a CAPTCHA with a Random Size and Text Length](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/random-size-and-text-length-captcha-2.png)
![Third Example of a CAPTCHA with a Random Size and Text Length](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/random-size-and-text-length-captcha-3.png)

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "botblock",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "",
    "keywords": "BotBlock,bot-block,Bot,Block,CAPTCHA,Spam,Protect,Form,Website,Self-Hosted,Self,Hosted,Privacy,Priveasy,P5vc",
    "author": "",
    "author_email": "Priveasy <Admin@Priveasy.org>",
    "download_url": "https://files.pythonhosted.org/packages/8f/b7/63ec0243a637d4d6f680bd92f49f53713eb143ce6ea4122808773f48b730/botblock-2.1.0.tar.gz",
    "platform": null,
    "description": "# BotBlock\n\n***A modern, self-hosted, privacy-respecting, CAPTCHA solution***\n\n------------\n\n# Table of Contents\n\n- [Overview](#overview \"Overview\")\n- [Implementation Details](#implementation-details \"Implementation Details\")\n- [Usage](#usage \"Usage\")\n  - [Installation](#installation \"Installation\")\n  - [Generating a Simple CAPTCHA](#generating-a-simple-captcha \"Generating a Simple CAPTCHA\")\n  - [Using the CAPTCHA Engine](#using-the-captcha-engine \"Using the CAPTCHA Engine\")\n  - [Customizing CAPTCHA Settings](#customizing-captcha-settings \"Customizing CAPTCHA Settings\")\n  - [Available Settings](#available-settings \"Available Settings\")\n- [Example CAPTCHAs](#example-captchas \"Example CAPTCHAs\")\n\n# Overview\n\nBotBlock 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.\n\nUnlike most other CAPTCHA solutions, BotBlock is open source, completely self-hosted, and does not require JavaScript.\n\nIf you are looking for a simple\u2014yet robust\u2014CAPTCHA solution that is customizable, easy to implement, privacy-respecting, and fully self-contained, BotBlock is the way to go!\n\n# Implementation Details\n\nBotBlock 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.\n\nBotBlock 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.\n\nBotBlock 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.\n\nWhen 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.\n\nPlease 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.\n\n\n# Usage\n\nThe full guide for developers on how to install, configure, and integrate BotBlock into their projects.\n\n## Installation\n\nThe easiest way to install BotBlock is to use `pip`:\n\n```bash\npip install botblock\n```\n\nOn some systems, you may need to run one of the following variations, instead:\n\n```bash\npython -m pip install botblock\n```\n\n```bash\npip3 install botblock\n```\n\n```bash\npython3 -m pip install botblock\n```\n\nUsing `pip` to 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:\n\n```\npython>=3.9\n\ncryptography>=39.0\nimportlib-resources>=5.12\nPillow>=9.4\n```\n\n## Generating a Simple CAPTCHA\n\nTo generate a simple CAPTCHA using BotBlock, you must first import the `Captcha` class:\n\n```python\nfrom botblock.captcha import Captcha\n```\n\nNext, instantiate a `Captcha` object with the default settings:\n\n```python\nmy_captcha = Captcha()\n```\n\nInstantiating a `Captcha` object will also automatically generate a CAPTCHA.\n\nTo save the CAPTCHA image for viewing, call the `save` method on your `Captcha` instance, and supply the full path of the image file you would like to create. For example:\n\n```python\nmy_captcha.save('/tmp/image.png')\n```\n\nYou can now open that image file with your favorite image viewer, to see the newly-generated CAPTCHA.\n\nTo increase efficiency and make embedding CAPTCHAs within webpages as easy as possible, you can also call the `base64` method on your `Captcha` instance to get its image data in base64 format, as a String:\n\n```python\nbase64_captcha_image = my_captcha.base64()\n```\n\nIf the (shortened, for this example) base64 data returned were `RXhhbXBsZSBDQVBUQ0hBIEltYWdlIERhdGE=`, you could embed it in a webpage using an `img` tag, like this:\n\n```html\n<img src=\"data:image/png;base64,RXhhbXBsZSBDQVBUQ0hBIEltYWdlIERhdGE=\" alt=\"BotBlock CAPTCHA\" />\n```\n\nLet'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 in `captcha.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.\n\nFeel 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.\n\n```python\nfrom botblock.captcha import Captcha\n\nmy_captcha = Captcha()\n\nwith open('captcha.html', 'w') as webpage:\n\twebpage.write('<!DOCTYPE html>\\n<html>\\n  <head>')\n\twebpage.write('\\n    <title>BotBlock CAPTCHA Example</title>')\n\twebpage.write('\\n  </head>\\n  <body>\\n    <div>')\n\twebpage.write('\\n      <p>Embedded BotBlock CAPTCHA:</p>')\n\twebpage.write('\\n      <img src=\"data:image/png;base64,')\n\twebpage.write(my_captcha.base64())\n\twebpage.write('\" alt=\"BotBlock CAPTCHA\" />')\n\twebpage.write('\\n    </div>\\n  </body>\\n</html>\\n')\n```\n\nTo get a CAPTCHA's solution, you can call the `get_solution` method on your `Captcha` instance, like so:\n\n```python\nsolution = my_captcha.get_solution()\n```\n\nKeep 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.\n\nIf you would like to see statistical information about a `Captcha` instance, you can call its `print_stats` method, or use `get_stats` to return the same information as a dictionary:\n\n```python\nstats = my_captcha.get_stats()\n# To print the Captcha instance's stats, you can use either of the following:\nmy_captcha.print_stats()\nprint(my_captcha)\n```\n\nFinally, the `generate` method can be called on your `Captcha` instance to regenerate its CAPTCHA image and metadata:\n\n```python\nmy_captcha.generate()\n```\n\nIn most circumstances, developers should never need to call this method. For small projects, new CAPTCHAs should be created by simply instantiating a new `Captcha` object or using an `Engine` instance. 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. The `generate` method is only provided for edge cases, because calling `generate` can be slightly more efficient than instantiating a completely new `Captcha` object. 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) `Engine` object to generate your CAPTCHAs, anyways.\n\n### Using the CAPTCHA Engine\n\nBotBlock'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, an `Engine` object is a much better option than manually generating and validating CAPTCHAs via a `Captcha` object. `Captcha` objects should really only be used for quick testing and unconventional use cases.\n\nAlthough the `Engine` object's lack of certain features provided by `Captcha` objects 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.\n\nWhen you instantiate an `Engine` object, three subprocesses are automatically created. The first subprocess instantiates a pool of `Captcha` instances, 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 the `Captcha` instances with the new settings. The second subprocess handles the automatic regeneration of used `Captcha` instances, 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.\n\nTo use BotBlock's CAPTCHA Engine, you must first import the `Engine` class, like so:\n\n```python\nfrom botblock.captcha import Engine\n```\n\nAfter importing the `Engine` class, you can instantiate an `Engine` object with the default settings:\n\n```python\nengine = Engine()\n```\n\nWhen using a CAPTCHA Engine, it's important to make sure that only one `Engine` object 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 different `Engine` instance than the one that generated the original CAPTCHA data. One `Engine` instance 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 separate *apps* within a Django *project*), then instantiating more than one CAPTCHA Engine may be appropriate.\n\nWhen you are finished using an `Engine` instance, that instance ***must*** be 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 an `Engine` instance, simply call its `shut_down` method:\n\n```python\nengine.shut_down()\n```\n\nThe `shut_down` method will block until the `Engine` instance has finished shutting down. This shouldn't take more than a few seconds at most.\n\nAlternatively, you can use a `with` statement with an `Engine` instance to automatically shut it down after the statement body finishes executing:\n\n```python\nwith Engine() as engine:\n    captcha = engine.get_captcha()\n```\n\nTo check if an `Engine` instance has been shut down, you can call its `is_shut_down` method:\n\n```python\nif engine.is_shut_down():\n\tprint('This Engine instance has been shut down.')\nelse:\n\tprint('This Engine instance is still active.')\n```\n\nTo get a fresh CAPTCHA from an `Engine` instance, you can call its `get_captcha` method. 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 an `Engine` instance:\n\n```python\n# Gets CAPTCHA data:\nfirst_captcha = engine.get_captcha()\n# Gets CAPTCHA data and saves CAPTCHA image to the specified file:\nsecond_captcha = engine.get_captcha('/tmp/captcha2.png')\n# Gets CAPTCHA data and then prints all of it:\nthird_captcha = engine.get_captcha()\nprint('Base64-Encoded CAPTCHA Image Data:')\nprint(third_captcha['base64_captcha'])\nprint('Encrypted Blob with CAPTCHA Authentication Data:')\nprint(third_captcha['encrypted_blob'])\n```\n\nFor 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 the [Generating a Simple CAPTCHA](#generating-a-simple-captcha \"Generating a Simple CAPTCHA\") section for examples of how to do this.\n\nWhen 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 the `Engine` instance to immediately recycle the `Captcha` instance 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.\n\nFor 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-tested `cryptography.fernet` library in Python.\n\nAlthough 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.\n\nOnce 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:\n\n```python\nencrypted_blob = get_authentication_data() # Made up function used for the example\nproposed_solution = get_proposed_solution() # Made up function used for the example\nif engine.validate(encrypted_blob, proposed_solution):\n\treturn \"Successfully solved the CAPTCHA\"\nelse:\n\treturn \"Failed to successfully solve the CAPTCHA\"\n```\n\nAn `Engine` instance's `validate` method will always return `False`, unless:\n\n- The authentication data can be successfully decrypted\n- The authentication data isn't older than the CAPTCHA's lifetime (the CAPTCHA isn't expired)\n- The proposed solution matches the correct solution\n- Validation hasn't already been attempted (successfully or unsuccessfully) with this encrypted blob\n\nFinally, to get statistical information about an `Engine` instance, you can call its `get_stats` method, to have the data returned as a dictionary. Alternatively, you can call `print_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 an `Engine` instance to compile the statistics, you may notice degraded query response speeds. Here's example output from calling `print_stats` on a production `Engine` instance:\n\n```\n>>> engine.print_stats()\nBOTBLOCK ENGINE INSTANCE\n\n    Shut Down: No\n    Active: 0 days, 16 hours, 21 minutes, and 30 seconds\n\n    Pool Size: 500\n    Fresh CAPTCHAs in Pool: 493\n    Used CAPTCHAs in Pool: 7\n\n    CAPTCHAs Distributed: 19630\n    Validation Attempts: 12442\n    CAPTCHA Solves: 10596\n\n    CAPTCHAs Generated per Hour: 1200.0\n    Validation Attempts per Hour: 760.59\n    CAPTCHA Solves per Hour: 647.74\n\n    Average Stats per Captcha Instance (500 Analyzed):\n        Average number of CAPTCHAs generated per Captcha Instance: 39.26\n        Average Font Size per Character per CAPTCHA: 122.35\n        Average Number of Character Colors Evaluated per CAPTCHA: 28.31\n        Average Number of Corrections to Character Positions per CAPTCHA: 1.54\n        Average Image Data Size (In Bytes) per CAPTCHA: 30784.54\n        Average Number of Layers of Noise Applied to Each CAPTCHA: 18.86\n\n    Settings:\n        WIDTH                                 = 750\n        HEIGHT                                = 250\n        FORMAT                                = 'PNG'\n        TEXT                                  = ''\n        TEXT_LENGTH                           = 6\n        CHARACTER_SET                         = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'\n        FONTS                                 = [\n                                                    'Amatic-Bold.ttf',\n                                                    'LifeSavers-Bold.ttf',\n                                                    'TungusFont_Tinet.ttf',\n                                                ]\n        CHARACTER_HORIZONTAL_SHIFT_PERCENTAGE = 65\n        CHARACTER_VERTICAL_SHIFT_PERCENTAGE   = 65\n        FONT_SIZE_SHIFT_PERCENTAGE            = 25\n        CHARACTER_OVERLAP_ENABLED             = False\n        MAXIMUM_NOISE                         = 25\n        MINIMUM_COLOR_BRIGHTNESS_DIFFERENCE   = 65\n        MINIMUM_COLOR_HUE_DIFFERENCE          = 250\n        CASE_SENSITIVE                        = False\n        LIFETIME                              = 600\n        POOL_SIZE                             = 500\n        RATE_LIMIT                            = 0\n```\n\n## Customizing CAPTCHA Settings\n\nNow that you can successfully generate and validate CAPTCHAs, it's time to learn how to customize them!\n\nAll of the settings used to generate CAPTCHAs and configure an Engine are stored within an instance of the `Settings` class. This class provides some important functionality, such as:\n\n- Validating provided settings\n- Using provided settings to pre-compute \"behind-the-scenes\" values needed during CAPTCHA generation\n- Allowing existing settings to be easily viewed, exported, or updated\n- Benchmarking different settings to provide an easy efficiency comparison\n\nTo use custom settings, the `Settings` class must first be imported, like so:\n\n```python\nfrom botblock.captcha import Settings\n```\n\nNow that the `Settings` class has been imported, you can instantiate a `Settings` object:\n\n```python\ndefault_settings = Settings()\n```\n\nBecause we didn't provide any arguments to the `Settings` object during instantiation, this instance will have the default settings values.\n\nTo view the current values that a `Settings` instance holds, you can call its `print_settings` method, or just print the instance itself:\n\n```python\ndefault_settings.print_settings()\nprint(default_settings)\n```\n\nTo retrieve the current settings as a dictionary, instead of printing them, you can use the `get_settings` method:\n\n```python\nsettings_dict = default_settings.get_settings()\n```\n\nIf you would like to compare a customized `Settings` instance's values to the default values, you can call the `print_default_settings` and `get_default_settings` methods, which function just like their respective `print_settings` and `get_settings` methods, as outlined above.\n\n```python\nif default_settings.get_settings() == default_settings.get_default_settings():\n    print('The current settings instance contains the default settings.')\nelse:\n    print('The current settings instance has been customized.')\n```\n\nTo create a `Settings` instance 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.\n\n```python\ncustom_settings = Settings(WIDTH = 825, HEIGHT = 275)\n```\n\nYou can also update the value of one or more settings after a `Settings` object has been instantiated, by calling its `set` method. Any settings not specified with a new value will maintain the value they had before the `set` method was called.\n\n```python\n# You can call `get_supported_image_formats` for a list of the supported image formats:\nnew_image_format = custom_settings.get_supported_image_formats()[1]\ncustom_settings.set(TEXT_LENGTH = 8, CASE_SENSITIVE = True, FORMAT = new_image_format)\n```\n\nEvery 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 your `Settings` instance back to the default values, with the `set_default_values` method:\n\n```python\ncustom_settings.set_default_values()\ncustom_settings.validate_settings() # Redundant; will raise an exception if invalid settings found\n```\n\nWhenever a `Captcha` or `Engine` object is instantiated without any arguments, it will create its own `Settings` instance with the default values. To have a `Captcha` or `Engine` instance use custom settings, you must provide a custom `Settings` object as an argument upon instantiation, or as an argument to the `update_settings` method:\n\n```python\nfrom botblock.captcha import *\n\ncustom_settings = Settings(WIDTH = 675, HEIGHT = 225)\ncustom_engine = Engine(custom_settings)\ncustom_captcha = Captcha()\n\ncustom_engine.update_settings(Settings(FORMAT = 'GIF'))\n\n# You can use the `get_settings` method to get the current `Settings` object:\ncaptcha_settings = custom_captcha.get_settings()\ncaptcha_settings.set(FORMAT = 'JPEG')\ncustom_captcha.update_settings(captcha_settings)\n\n# Provide no `Settings` instance as an argument, to restore the default settings:\ncustom_engine.update_settings()\n```\n\nModifying 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, the `Settings` class 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.\n\nTo run an efficiency benchmark, simply instantiate a `Settings` object with your desired settings, then call its `compare_efficiency` method. You can pass another `Settings` instance 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).\n\n```python\nfirst_settings = Settings(TEXT_LENGTH = 10)\nsecond_settings = Settings(TEXT_LENGTH = 5)\nfirst_settings.compare_efficiency(second_settings)\n\nfirst_settings.compare_efficiency(settings = Settings(TEXT_LENGTH = 3), test_length = 120)\n```\n\nWhen running a benchmark, please keep in mind that:\n\n- 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.\n- 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.\n- 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. one `Settings` instance is always found to me more efficient than the other), then you can feel much more confident about the accuracy of those results.\n- 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 utilizes `Captcha` objects 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 between `Settings` instances should still be accurate for `Engine` objects.\n- 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.\n\n## Available Settings\n\nThis section serves as a reference for each available setting that a developer may customize.\n\n### WIDTH\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `750`\n\n**Must Be:**\n\n- Of type `int`\n- Greater in value than `9`\n- Greater or equal in value to the `HEIGHT` setting's value\n\n**Efficiency Impact:**\n\nIn general, the greater the value, the lesser the efficiency\n\n**Description:**\n\nSets the width of the CAPTCHA image to generate, in pixels\n\n### HEIGHT\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `250`\n\n**Must Be:**\n\n- Of type `int`\n- Greater in value than `4`\n- Lesser or equal in value to the `WIDTH` setting's value\n\n**Efficiency Impact:**\n\nIn general, the greater the value, the lesser the efficiency\n\n**Description:**\n\nSets the height of the CAPTCHA image to generate, in pixels\n\n### FORMAT\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `'PNG'`\n\n**Must Be:**\n\n- Of type `str`\n- Equal to one of the following values:\n  - `'BMP'`\n  - `'GIF'`\n  - `'ICO'`\n  - `'JPEG'`\n  - `'PNG'`\n  - `'TIFF'`\n  - `'WEBP'`\n  - `'PDF'`\n\n**Efficiency Impact:**\n\nImage formats in order of average generation speed (from quickest to slowest):\n\n- JPEG\n- PDF\n- BMP\n- TIFF\n- PNG\n- ICO\n- WEBP\n- GIF\n\nImage formats in order of average file size (from smallest to largest):\n\n- GIF\n- ICO\n- WEBP\n- PNG\n- JPEG\n- PDF\n- TIFF\n- BMP\n\n*Note: results may vary by system*\n\n**Description:**\n\nSets the image format of the generated CAPTCHA image\n\nThe PNG and JPEG image formats are highly recommended due to their widespread support, quick generation speed, and relatively small file sizes.\n\nThe 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.\n\n### TEXT\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `''`\n\n**Must Be:**\n\n- Of type `str`\n- Empty, or greater in length than `2`\n\n**Efficiency Impact:**\n\nIn general, the greater the length, the lesser the efficiency\n\n**Description:**\n\nSets custom CAPTCHA text to use\n\nWhen blank, CAPTCHA text will be randomly generated using characters from the `CHARACTER_SET` setting. Otherwise, CAPTCHA text (and therefore the solution) will always be equal to this value (negating the `CHARACTER_SET` and `TEXT_LENGTH` settings).\n\n### TEXT_LENGTH\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `6`\n\n**Must Be:**\n\n- Of type `int`\n- Greater in value than `2`\n\n**Efficiency Impact:**\n\nIn general, the lesser the value, the greater the efficiency\n\n**Description:**\n\nSets the length of randomly-generated CAPTCHA text/solutions\n\nBe 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, say `10,000`, then a malicious user could write code to automatically submit a form `10,000,000` times, with a random guess of the solution each time, and expect about `1,000` of those submissions to be excepted as valid.\n\nUsing the default character set with case sensitivity disabled (also the default), this is how many possible solutions there are for the first ten `TEXT_LENGTH` values:\n\n| TEXT_LENGTH |      Solutions      |\n|-------------|---------------------|\n|      1      |                  31 |\n|      2      |                 961 |\n|      3      |              29,791 |\n|      4      |             923,521 |\n|      5      |          28,629,151 |\n|      6      |         887,503,681 |\n|      7      |      27,512,614,111 |\n|      8      |     852,891,037,441 |\n|      9      |  26,439,622,160,671 |\n|     10      | 819,628,286,980,801 |\n\nThe 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.\n\n### CHARACTER_SET\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'`\n\n**Must Be:**\n\n- Of type `str`\n- Greater in length than `0` when the `TEXT` setting is blank\n- Comprised of unique characters\n\n**Efficiency Impact:**\n\nLonger character sets are slightly more efficient than shorter ones\n\n**Description:**\n\nSets the character set from which random characters are chosen for the CAPTCHA text, when no custom text is provided via the `TEXT` setting\n\nWhen designing a custom character set, you should keep the following in mind:\n\n- The character set should be relatively large (even with case sensitivity disabled), in order to increase bruteforce resistance\n- The character set should still include mixed-case characters (if applicable) when case sensitivity is disabled, to increase the variability of CAPTCHA images\n- The character set should only include characters that are easily-recognizable for your users\n- The character set should not contain any characters that aren't commonly found on the keyboards of your users, or that they don't commonly type\n- The 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`, and `1`)\n- The character set should not contain any characters that Python doesn't know how to properly iterate over\n\n### FONTS\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `['Amatic-Bold.ttf', 'LifeSavers-Bold.ttf', 'TungusFont_Tinet.ttf']`\n\n**Must Be:**\n\n- Of type `list` and containing one or more `str` types, which represent paths to valid font files\n\n**Efficiency Impact:**\n\nVariable, based on the typeface(s) provided\n\n**Description:**\n\nSets the fonts that are chosen at random to render each character in the CAPTCHA image\n\nIf 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.\n\n*Note: the default fonts, while all open source, do not fall under this repository's MIT license. Navigate to the `fonts` directory in this repository to view each font's license.*\n\n### CHARACTER_HORIZONTAL_SHIFT_PERCENTAGE\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `65`\n\n**Must Be:**\n\n- Of type `int`\n- A whole number less than `101` in value\n\n**Efficiency Impact:**\n\nNegligible\n\n**Description:**\n\nSets the maximum percentage to horizontally shift characters\n\nDuring 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.\n\n### CHARACTER_VERTICAL_SHIFT_PERCENTAGE\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `65`\n\n**Must Be:**\n\n- Of type `int`\n- A whole number less than `101` in value\n\n**Efficiency Impact:**\n\nNegligible\n\n**Description:**\n\nSets the maximum percentage to vertically shift characters\n\nDuring 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.\n\n### FONT_SIZE_SHIFT_PERCENTAGE\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `25`\n\n**Must Be:**\n\n- Of type `int`\n- A whole number less than `101` in value\n\n**Efficiency Impact:**\n\nNegligible\n\n**Description:**\n\nSets the maximum percentage to shift characters' font sizes\n\nDuring 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.\n\n### CHARACTER_OVERLAP_ENABLED\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `False`\n\n**Must Be:**\n\n- Of type `bool`\n\n**Efficiency Impact:**\n\nIn general, when set to `True`, CAPTCHA generation is more efficient\n\n**Description:**\n\nWhen `False`, 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. When `True`, 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 the `CHARACTER_HORIZONTAL_SHIFT_PERCENTAGE` and `CHARACTER_VERTICAL_SHIFT_PERCENTAGE` settings' values are high.\n\n### MAXIMUM_NOISE\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `25`\n\n**Must Be:**\n\n- Of type `int`\n- A whole number\n\n**Efficiency Impact:**\n\nIn general, the greater the value, the lesser the efficiency\n\n**Description:**\n\nSets the maximum number of layers of noise to apply to a CAPTCHA\n\nWhen 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.\n\n### MINIMUM_COLOR_BRIGHTNESS_DIFFERENCE\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `65`\n\n**Must Be:**\n\n- Of type `int`\n- Less than `201` in value\n\n**Efficiency Impact:**\n\nIn general, the greater the value, the lesser the efficiency\n\n**Description:**\n\nSets the minimum color brightness difference between the CAPTCHA background color and the CAPTCHA text color\n\nWhen 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.\n\nThe default value of this setting (combined with the default value of the `MINIMUM_COLOR_HUE_DIFFERENCE` setting) 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.\n\nWhile 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 least `125`, to ensure compliance with web accessibility standards.\n\n### MINIMUM_COLOR_HUE_DIFFERENCE\n\n**Applies To:** CAPTCHAs\n\n**Default Value:** `250`\n\n**Must Be:**\n\n- Of type `int`\n- Less than `601` in value\n\n**Efficiency Impact:**\n\nIn general, the greater the value, the lesser the efficiency\n\n**Description:**\n\nSets the minimum color hue difference between the CAPTCHA background color and the CAPTCHA text color\n\nWhen 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.\n\nThe default value of this setting (combined with the default value of the `MINIMUM_COLOR_BRIGHTNESS_DIFFERENCE` setting) 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.\n\nWhile 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 least `500`, to ensure compliance with web accessibility standards.\n\n### CASE_SENSITIVE\n\n**Applies To:** Engines\n\n**Default Value:** `False`\n\n**Must Be:**\n\n- Of type `bool`\n\n**Efficiency Impact:**\n\nNegligible\n\n**Description:**\n\nWhen `True`, provided solutions must match the case (uppercase or lowercase) of the CAPTCHA text in order for the Engine's `validate` method to conclude that the solution is valid. For example:\n\n| CAPTCHA Text | User's Solution | Considered Valid |\n|--------------|-----------------|------------------|\n|    NfBnhB    |      NfBnhB     |       True       |\n|    CSKteH    |      cskteh     |       False      |\n|    FSv52h    |      FSV52H     |       False      |\n|    Tav3dH    |      TaV3dH     |       False      |\n\nWhen `False`, the Engine's `validate` method 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:\n\n| CAPTCHA Text | User's Solution | Considered Valid |\n|--------------|-----------------|------------------|\n|    NfBnhB    |      NfBnhB     |       True       |\n|    CSKteH    |      cskteh     |       True       |\n|    FSv52h    |      FSV52H     |       True       |\n|    Tav3dH    |      TaV3dH     |       True       |\n\nIt is highly recommended to use the default value of `False` for 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).\n\nIt should also be noted that when this setting is set to `False`, Python's `str.lower` method 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 to `True`.\n\n###06597ba1cfc49461462bfd3896895253a067ddf2 LIFETIME\n\n**Applies To:** Engines\n\n**Default Value:** `600`\n\n**Must Be:**\n\n- Of type `int`\n- A whole number\n\n**Efficiency Impact:**\n\nNegligible in most use cases\n\n**Description:**\n\nSets the lifetime (in seconds) of CAPTCHAs, after which they expire\n\nAny 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 is `600` seconds, or ten minutes, but any time between `30` seconds and `1800` seconds (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.\n\n### POOL_SIZE\n\n**Applies To:** Engines\n\n**Default Value:** `500`\n\n**Must Be:**\n\n- Of type `int`\n- A natural number\n\n**Efficiency Impact:**\n\nVariable, depending on query rate and variance, host system specifications, and more\n\n**Description:**\n\nSets an Engine's fresh `Captcha` instance pool size\n\nIn order to increase efficiency and query response speeds, and allow for burstable performance, Engine objects create and maintain a pool of fresh `Captcha` instances, 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 the `POOL_SIZE` setting's value. On the other hand, if running on a system with very limited memory, you may wish to decrease this setting's value.\n\nNote: this is the only setting that cannot be dynamically updated.\n\n### RATE_LIMIT\n\n**Applies To:** Engines\n\n**Default Value:** `0`\n\n**Must Be:**\n\n- Of type `int`\n- A whole number\n\n*OR*\n\n- Of type `float`\n- Greater in value than `0.0`\n\n**Efficiency Impact:**\n\nNo impact on CAPTCHA generation efficiency when disabled (default), very slight impact when enabled\n\nThe lesser the integer value (still greater than `0`), the lower the average CPU usage by BotBlock\n\nThe greater the floating point value, the lower the average CPU usage by BotBlock\n\n**Description:**\n\nLimits the number of CAPTCHAs that may be generated per minute\n\nFor 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:\n\nWhen 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.\n\nWhen 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.\n\nAll rate limiting can be disabled by making this setting's value equal to `0`.\n\nNote: the rate limiting does not apply to the initial CAPTCHA generation (to fill the pool) that occurs when an `Engine` is first instantiated. It will also not apply to the regeneration that occurs when an `Engine` instance's settings are updated.\n\n# Example CAPTCHAs\n\nHere 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.\n\n### CAPTCHAs generated using the default settings:\n\n![First Example of a Default CAPTCHA](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-1.png)\n![Second Example of a Default CAPTCHA](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-2.png)\n![Third Example of a Default CAPTCHA](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-3.png)\n\n### CAPTCHAs generated with default settings and saved as JPEGs:\n\n![First Example of a Default CAPTCHA Saved as a JPEG](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-1.jpeg)\n![Second Example of a Default CAPTCHA Saved as a JPEG](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-2.jpeg)\n![Third Example of a Default CAPTCHA Saved as a JPEG](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/default-captcha-3.jpeg)\n\n### CAPTCHAs generated with higher contrast and low noise:\n\n![First Example of a CAPTCHA with Higher Contrast and Low Noise](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-contrast-low-noise-captcha-1.png)\n![Second Example of a CAPTCHA with Higher Contrast and Low Noise](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-contrast-low-noise-captcha-2.png)\n![Third Example of a CAPTCHA with Higher Contrast and Low Noise](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-contrast-low-noise-captcha-3.png)\n\n### CAPTCHAs generated with high noise and character overlap enabled:\n\n![First Example of a CAPTCHA with High Noise and Character Overlap](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-noise-character-overlap-captcha-1.png)\n![Second Example of a CAPTCHA with High Noise and Character Overlap](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-noise-character-overlap-captcha-2.png)\n![Third Example of a CAPTCHA with High Noise and Character Overlap](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/high-noise-character-overlap-captcha-3.png)\n\n### CAPTCHAs of various sizes and text lengths:\n\n![First Example of a CAPTCHA with a Random Size and Text Length](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/random-size-and-text-length-captcha-1.png)\n![Second Example of a CAPTCHA with a Random Size and Text Length](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/random-size-and-text-length-captcha-2.png)\n![Third Example of a CAPTCHA with a Random Size and Text Length](https://source.priveasy.org/Priveasy/bot-block/raw/branch/main/examples/random-size-and-text-length-captcha-3.png)\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2023 Priveasy  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ",
    "summary": "A modern, self-hosted, privacy-respecting, CAPTCHA solution",
    "version": "2.1.0",
    "split_keywords": [
        "botblock",
        "bot-block",
        "bot",
        "block",
        "captcha",
        "spam",
        "protect",
        "form",
        "website",
        "self-hosted",
        "self",
        "hosted",
        "privacy",
        "priveasy",
        "p5vc"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "55fa49104a66e995123f69a73930552fef1dbbb83790cb5227f08df2fcafe3cc",
                "md5": "e941d46b659bb0f5f8d3368bf925c4b5",
                "sha256": "01b634c23a175ed7762b42b6fad2e17ad27c893dce04aba0c25b23488f88e61b"
            },
            "downloads": -1,
            "filename": "botblock-2.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e941d46b659bb0f5f8d3368bf925c4b5",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 193230,
            "upload_time": "2023-03-25T02:50:02",
            "upload_time_iso_8601": "2023-03-25T02:50:02.571753Z",
            "url": "https://files.pythonhosted.org/packages/55/fa/49104a66e995123f69a73930552fef1dbbb83790cb5227f08df2fcafe3cc/botblock-2.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8fb763ec0243a637d4d6f680bd92f49f53713eb143ce6ea4122808773f48b730",
                "md5": "5302ee1041dfe92749f675b69fc052d6",
                "sha256": "0b140dd7ee62a08ad8fc7a4622ea52e88fcb0d43207774e5e78830f4475cc242"
            },
            "downloads": -1,
            "filename": "botblock-2.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "5302ee1041dfe92749f675b69fc052d6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 220113,
            "upload_time": "2023-03-25T02:50:06",
            "upload_time_iso_8601": "2023-03-25T02:50:06.224505Z",
            "url": "https://files.pythonhosted.org/packages/8f/b7/63ec0243a637d4d6f680bd92f49f53713eb143ce6ea4122808773f48b730/botblock-2.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-03-25 02:50:06",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "lcname": "botblock"
}
        
Elapsed time: 0.28377s