Logo dropzone.js

DropzoneJS is an open source library that provides drag’n’drop file uploads with image previews.

It’s lightweight, doesn’t depend on any other library (like jQuery) and is highly customizable.

Scroll down!

Try it out!

(This is just a demo dropzone. Selected files are not actually uploaded.)


Dropzone 5.7.2, July 23rd 2020

Lots of minor fixes in this small release. Please check the CHANGELOG to see a summary of the changes.

I know that most of you are unhappy that I can’t fix all bugs and implement all feature requests immediately, but I have a job and I’m doing my best to maintain this library for over eight years now.

Please stay respectful and patient. I’m doing my best to keep this alive and maintained in my free time without getting paid for it.

Well crafted merge requests are the fastest way to get your feature into Dropzone!

If you want to support me or thank me for the work I’ve put into Dropzone, check out my latest music video and leave a like if you feel like it:

And don’t forget: don’t be an asshole! ❤️


You probably only need to look at the simple example (source) to get started. Continue reading for step by step instructions and different installation approaches.

Download the standalone dropzone.js and include it like this:

<script src="./path/to/dropzone.js"></script>

Dropzone is now activated and available as window.Dropzone.

Dropzone does not handle your file uploads on the server. You have to implement the code to receive and store the file yourself. See the section Server side implementation for more information.

This is all you need to get dropzone up and running, but if you want it to look like the dropzone on this page, you’ll need to use the dropzone.css in the dist folder.

With RequireJS

Dropzone is also available as an AMD module for RequireJS.

You can find the dropzone-amd-module in the dist folder.


The typical way of using dropzone is by creating a form element with the class dropzone:

<form action="/file-upload"

That’s it. Dropzone will find all form elements with the class dropzone, automatically attach itself to it, and upload files dropped into it to the specified action attribute. The uploaded files can be handled just as if there would have been a html input like this:

<input type="file" name="file" />

If you want another name than file you can configure dropzone with the option paramName.

If you want your file uploads to work even without JavaScript, you can include an element with the class fallback that dropzone will remove if the browser is supported. If the browser isn’t supported, Dropzone will not create fallback elements if there is a fallback element already provided. (Obviously, if the browser doesn’t support JavaScript, the form will stay as is)

Typically this will look like this:

<form action="/file-upload" class="dropzone">
  <div class="fallback">
    <input name="file" type="file" multiple />

Create dropzones programmatically

Alternatively you can create dropzones programmaticaly (even on non form elements) by instantiating the Dropzone class

// Dropzone class:
var myDropzone = new Dropzone("div#myId", { url: "/file/post"});

or if you use jQuery, you can use the jQuery plugin Dropzone ships with:

// jQuery
$("div#myId").dropzone({ url: "/file/post" });

Don’t forget to specify an url option if you’re not using a form element, since Dropzone doesn’t know where to post to without an action attribute.

Server side implementation

Dropzone does not provide the server side implementation of handling the files, but the way files are uploaded is identical to simple file upload forms like this:

<form action="" method="post" enctype="multipart/form-data">
  <input type="file" name="file" />

To handle basic file uploads on the server, please look at the corresponding documentation. Here are a few documentations, if you think I should add some, please contact me.

Paid documentations:

Please look at the Dropzone FAQ if you need more information.


There are two ways to configure dropzones.

The obvious way is to pass an options object when instantiating a dropzone programmatically like in the previous create dropzones programmatically section.

But if you just have HTML elements with the dropzone class, then you don’t programmatically instantiate the objects, so you have to store the configuration somewhere so Dropzone knows how to configure the dropzones when instantiating them.

This is done with the Dropzone.options object.

// "myAwesomeDropzone" is the camelized version of the HTML element's ID
Dropzone.options.myAwesomeDropzone = {
  paramName: "file", // The name that will be used to transfer the file
  maxFilesize: 2, // MB
  accept: function(file, done) {
    if (file.name == "justinbieber.jpg") {
      done("Naha, you don't.");
    else { done(); }

If you want to disable the auto discover behaviour of Dropzone, you can either disable it on a per element basis, or in general:

// Prevent Dropzone from auto discovering this element:
Dropzone.options.myAwesomeDropzone = false;
// This is useful when you want to create the
// Dropzone programmatically later

// Disable auto discover for all elements:
Dropzone.autoDiscover = false;

Configuration options

Configuration options
url default: null

Has to be specified on elements other than form (or when the form doesn't have an action attribute). You can also provide a function that will be called with files and must return the url (since v3.12.0)

method default: "post"

Can be changed to "put" if necessary. You can also provide a function that will be called with files and must return the method (since v3.12.0).

withCredentials default: false

Will be set on the XHRequest.

timeout default: 30000

The timeout for the XHR requests in milliseconds (since v4.4.0).

parallelUploads default: 2

How many file uploads to process in parallel (See the Enqueuing file uploads documentation section for more info)

uploadMultiple default: false

Whether to send multiple files in one request. If this it set to true, then the fallback file input element will have the multiple attribute as well. This option will also trigger additional events (like processingmultiple). See the events documentation section for more information.

chunking default: false

Whether you want files to be uploaded in chunks to your server. This can't be used in combination with uploadMultiple.

See chunksUploaded for the callback to finalise an upload.

forceChunking default: false

If chunking is enabled, this defines whether every file should be chunked, even if the file size is below chunkSize. This means, that the additional chunk form data will be submitted and the chunksUploaded callback will be invoked.

chunkSize default: 2000000

If chunking is true, then this defines the chunk size in bytes.

parallelChunkUploads default: false

If true, the individual chunks of a file are being uploaded simultaneously.

retryChunks default: false

Whether a chunk should be retried if it fails.

retryChunksLimit default: 3

If retryChunks is true, how many times should it be retried.

maxFilesize default: 256

If not null defines how many files this Dropzone handles. If it exceeds, the event maxfilesexceeded will be called. The dropzone element gets the class dz-max-files-reached accordingly so you can provide visual feedback.

paramName default: "file"

The name of the file param that gets transferred. NOTE: If you have the option uploadMultiple set to true, then Dropzone will append [] to the name.

createImageThumbnails default: true

Whether thumbnails for images should be generated

maxThumbnailFilesize default: 10

In MB. When the filename exceeds this limit, the thumbnail will not be generated.

thumbnailWidth default: 120

If null, the ratio of the image will be used to calculate it.

thumbnailHeight default: 120

The same as thumbnailWidth. If both are null, images will not be resized.

thumbnailMethod default: 'crop'

How the images should be scaled down in case both, thumbnailWidth and thumbnailHeight are provided. Can be either contain or crop.

resizeWidth default: null

If set, images will be resized to these dimensions before being uploaded. If only one, resizeWidth or resizeHeight is provided, the original aspect ratio of the file will be preserved.

The options.transformFile function uses these options, so if the transformFile function is overridden, these options don't do anything.

resizeHeight default: null

See resizeWidth.

resizeMimeType default: null

The mime type of the resized image (before it gets uploaded to the server). If null the original mime type will be used. To force jpeg, for example, use image/jpeg. See resizeWidth for more information.

resizeQuality default: 0.8

The quality of the resized images. See resizeWidth.

resizeMethod default: 'contain'

How the images should be scaled down in case both, resizeWidth and resizeHeight are provided. Can be either contain or crop.

filesizeBase default: 1000

The base that is used to calculate the filesize. You can change this to 1024 if you would rather display kibibytes, mebibytes, etc... 1024 is technically incorrect, because 1024 bytes are 1 kibibyte not 1 kilobyte. You can change this to 1024 if you don't care about validity.

maxFiles default: null

Can be used to limit the maximum number of files that will be handled by this Dropzone

headers default: null

An optional object to send additional headers to the server. Eg: { "My-Awesome-Header": "header value" }

clickable default: true

If true, the dropzone element itself will be clickable, if false nothing will be clickable.

You can also pass an HTML element, a CSS selector (for multiple elements) or an array of those. In that case, all of those elements will trigger an upload when clicked.

ignoreHiddenFiles default: true

Whether hidden files in directories should be ignored.

acceptedFiles default: null

The default implementation of accept checks the file's mime type or extension against this list. This is a comma separated list of mime types or file extensions.

Eg.: image/*,application/pdf,.psd

If the Dropzone is clickable this option will also be used as accept parameter on the hidden file input as well.

acceptedMimeTypes default: null

Deprecated! Use acceptedFiles instead.

autoProcessQueue default: true

If false, files will be added to the queue but the queue will not be processed automatically. This can be useful if you need some additional user input before sending files (or if you want want all files sent at once). If you're ready to send the file simply call myDropzone.processQueue().

See the enqueuing file uploads documentation section for more information.

autoQueue default: true

If false, files added to the dropzone will not be queued by default. You'll have to call enqueueFile(file) manually.

previewsContainer default: null

Defines where to display the file previews – if null the Dropzone element itself is used. Can be a plain HTMLElement or a CSS selector. The element should have the dropzone-previews class so the previews are displayed properly.

hiddenInputContainer default: "body"

This is the element the hidden input field (which is used when clicking on the dropzone to trigger file selection) will be appended to. This might be important in case you use frameworks to switch the content of your page.

Can be a selector string, or an element directly.

capture default: null

If null, no capture type will be specified If camera, mobile devices will skip the file selection and choose camera If microphone, mobile devices will skip the file selection and choose the microphone If camcorder, mobile devices will skip the file selection and choose the camera in video mode On apple devices multiple must be set to false. AcceptedFiles may need to be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").

renameFilename default: null

Deprecated. Use renameFile instead.

renameFile default: null

A function that is invoked before the file is uploaded to the server and renames the file. This function gets the File as argument and can use the file.name. The actual name of the file that gets used during the upload can be accessed through file.upload.filename.

forceFallback default: false

If true the fallback will be forced. This is very useful to test your server implementations first and make sure that everything works as expected without dropzone if you experience problems, and to test how your fallbacks will look.

to translate dropzone, you can provide these options:
dictDefaultMessage default: see description

The text used before any files are dropped.

dictFallbackMessage default: see description

The text that replaces the default message text it the browser is not supported.

dictFallbackText default: see description

The text that will be added before the fallback form. If you provide a fallback element yourself, or if this option is null this will be ignored.

dictFileTooBig default: see description

If the filesize is too big. {{filesize}} and {{maxFilesize}} will be replaced with the respective configuration values.

dictInvalidFileType default: see description

If the file doesn't match the file type.

dictResponseError default: see description

If the server response was invalid. {{statusCode}} will be replaced with the servers status code.

dictCancelUpload default: see description

If addRemoveLinks is true, the text to be used for the cancel upload link.

dictUploadCanceled default: see description

The text that is displayed if an upload was manually canceled

dictCancelUploadConfirmation default: see description

If addRemoveLinks is true, the text to be used for confirmation when cancelling upload.

dictRemoveFile default: see description

If addRemoveLinks is true, the text to be used to remove a file.

dictRemoveFileConfirmation default: see description

If this is not null, then the user will be prompted before removing a file.

dictMaxFilesExceeded default: see description

Displayed if maxFiles is st and exceeded. The string {{maxFiles}} will be replaced by the configuration value.

dictFileSizeUnits default: see description

Allows you to translate the different units. Starting with tb for terabytes and going down to b for bytes.

functions you can override to change or extend default behavior:
init default: function

Called when dropzone initialized You can add event listeners here

params default: function

Can be an object of additional parameters to transfer to the server, or a Function that gets invoked with the files, xhr and, if it's a chunked upload, chunk arguments. In case of a function, this needs to return a map.

The default implementation does nothing for normal uploads, but adds relevant information for chunked uploads.

This is the same as adding hidden input fields in the form element.

accept default: function

A function that gets a file and a done function as parameters.

If the done function is invoked without arguments, the file is "accepted" and will be processed. If you pass an error message, the file is rejected, and the error message will be displayed. This function will not be called if the file is too big or doesn't match the mime types.

chunksUploaded default: function

The callback that will be invoked when all chunks have been uploaded for a file. It gets the file for which the chunks have been uploaded as the first parameter, and the done function as second. done() needs to be invoked when everything needed to finish the upload process is done.

fallback default: function

Gets called when the browser is not supported. The default implementation shows the fallback input field and adds a text.

resize default: function

Gets called to calculate the thumbnail dimensions.

It gets file, width and height (both may be null) as parameters and must return an object containing:

  • srcWidth & srcHeight (required)
  • trgWidth & trgHeight (required)
  • srcX & srcY (optional, default 0)
  • trgX & trgY (optional, default 0)

Those values are going to be used by ctx.drawImage().

transformFile default: function

Can be used to transform the file (for example, resize an image if necessary).

The default implementation uses resizeWidth and resizeHeight (if provided) and resizes images according to those dimensions.

Gets the file as the first parameter, and a done() function as the second, that needs to be invoked with the file when the transformation is done.

previewTemplate default: HTML template

A string that contains the template used for each dropped file. Change it to fulfill your needs but make sure to properly provide all elements.

If you want to use an actual HTML element instead of providing a String as a config option, you could create a div with the id tpl, put the template inside it and provide the element like this:


You can also overwrite all default event actions in the options. So if you provide the option drop you can overwrite the default drop event handler. You should be familiar with the code if you do that because you can easily break the upload like this. If you just want to do additional stuff, like adding a few classes here and there, listen to the events instead!

Enqueuing file uploads

When a file gets added to the dropzone, its status gets set to Dropzone.QUEUED (after the accept function check passes) which means that the file is now in the queue.

If you have the option autoProcessQueue set to true then the queue is immediately processed, after a file is dropped or an upload finished, by calling .processQueue() which checks how many files are currently uploading, and if it’s less than options.parallelUploads, .processFile(file) is called.

If you set autoProcessQueue to false, then .processQueue() is never called implicitly. This means that you have to call it yourself when you want to upload all files currently queued.


The HTML that is generated for each file by dropzone is defined with the option previewTemplate which defaults to this:

<div class="dz-preview dz-file-preview">
  <div class="dz-details">
    <div class="dz-filename"><span data-dz-name></span></div>
    <div class="dz-size" data-dz-size></div>
    <img data-dz-thumbnail />
  <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
  <div class="dz-success-mark"><span></span></div>
  <div class="dz-error-mark"><span></span></div>
  <div class="dz-error-message"><span data-dz-errormessage></span></div>

The container (dz-preview) gets the dz-processing class when the file gets processed, dz-success when the file got uploaded and dz-error in case the file couldn’t be uploaded. In the latter case, data-dz-errormessage will contain the text returned by the server.

To overwrite the default template, use the previewTemplate config.

You can access the HTML of the file preview in any of the events with file.previewElement.

If you decide to rewrite the previewTemplate from scratch, you should put elements with the data-dz-* attributes inside:

The default options for Dropzone will look for those element and update the content for it.

If you want some specific link to remove a file (instead of the built in addRemoveLinks config), you can simply insert elements in the template with the data-dz-remove attribute. Example:

<img src="removebutton.png" alt="Click me to remove the file." data-dz-remove />

You are not forced to use those conventions though. If you override all the default event listeners you can completely rebuild your layout from scratch.

See the installation section on how to add the stylesheet and spritemaps if you want your dropzone to look like the one on this page.

See the Theming section, for a more in depth look at how to change Dropzone’s UI.

I created an example where I made Dropzone look and feel exactly the way jQuery File Uploader does with a few lines of configuration code. Check it out!

Again, please look at the Dropzone FAQ if you’re still unclear about some features.

Dropzone methods

If you want to remove an added file from the dropzone, you can call .removeFile(file). This method also triggers the removedfile event.

Here’s an example that would automatically remove a file when it’s finished uploading:

myDropzone.on("complete", function(file) {

If you want to remove all files, simply use .removeAllFiles(). Files that are in the process of being uploaded won’t be removed. If you want files that are currently uploading to be canceled, call .removeAllFiles(true) which will cancel the uploads.

If you have autoProcessQueue disabled, you’ll need to call .processQueue() yourself.

This can be useful if you want to display the files and let the user click an accept button to actually upload the file(s).

To access all files in the dropzone, use myDropzone.files.

To get

If you do not need a dropzone anymore, just call .disable() on the object. This will remove all event listeners on the element, and clear all file arrays. To reenable a Dropzone use .enable().

If you don’t like the default browser modals for confirm calls, you can handle them yourself by overwriting Dropzone.confirm.

Dropzone.confirm = function(question, accepted, rejected) {
  // Ask the question, and call accepted() or rejected() accordingly.
  // CAREFUL: rejected might not be defined. Do nothing in that case.

If you want Dropzone to display an image you have on your server, you can use:

// callback and crossOrigin are optional
let mockFile = { name: "Filename", size: 12345 };
myDropzone.displayExistingFile(mockFile, 'https://image-url');

See the FAQ on How to show files stored on server for more information.


Dropzone triggers events when processing files, to which you can register easily, by calling .on(eventName, callbackFunction) on your instance.

Since listening to events can only be done on instances of Dropzone, the best place to setup your event listeners, is in the init function:

// The recommended way from within the init configuration:
Dropzone.options.myAwesomeDropzone = {
  init: function() {
    this.on("addedfile", function(file) { alert("Added file."); });

If you create your Dropzones programmatically, you can setup your event listeners on your instances, like this:

// This example uses jQuery so it creates the Dropzone, only when the DOM has
// loaded.

// Disabling autoDiscover, otherwise Dropzone will try to attach twice.
Dropzone.autoDiscover = false;
// or disable for specific dropzone:
// Dropzone.options.myDropzone = false;

$(function() {
  // Now that the DOM is fully loaded, create the dropzone, and setup the
  // event listeners
  var myDropzone = new Dropzone("#my-dropzone");
  myDropzone.on("addedfile", function(file) {
    /* Maybe display some more file information on your page */

This is a bit more complex, and not necessary unless you have a good reason to instantiate Dropzones programmatically.

Dropzone itself relies heavily on events. Everything that’s visual is created by listening to them. Those event listeners are setup in the default configuration of every Dropzone and can be overwritten, thus replacing the default behavior with your own event callback.

You should only do this when you really know how Dropzone works, and when you want to completely theme your Dropzone

Event List

Event list

Do not overwrite those as configuration options, unless you know what you're doing.

All of these receive the event as first parameter:
drop The user dropped something onto the dropzone
dragstart The user started to drag anywhere
dragend Dragging has ended
dragenter The user dragged a file onto the Dropzone
dragover The user is dragging a file over the Dropzone
dragleave The user dragged a file out of the Dropzone
All of these receive the file as first parameter:
addedfile When a file is added to the list
removedfile Called whenever a file is removed from the list. You can listen to this and delete the file from your server if you want to.
thumbnail When the thumbnail has been generated. Receives the dataUrl as second parameter.
error An error occured. Receives the errorMessage as second parameter and if the error was due to the XMLHttpRequest the xhr object as third.
processing When a file gets processed (since there is a queue not all files are processed immediately). This event was called processingfile previously.
uploadprogress Gets called periodically whenever the file upload progress changes.
Gets the progress parameter as second parameter which is a percentage (0-100) and the bytesSent parameter as third which is the number of the bytes that have been sent to the server.
When an upload finishes dropzone ensures that uploadprogress will be called with a percentage of 100 at least once.
Warning: This function can potentially be called with the same progress multiple times.
sending Called just before each file is sent. Gets the xhr object and the formData objects as second and third parameters, so you can modify them (for example to add a CSRF token) or add additional data.
success The file has been uploaded successfully. Gets the server response as second argument. (This event was called finished previously)
complete Called when the upload was either successful or erroneous.
canceled Called when a file upload gets canceled.
maxfilesreached Called when the number of files accepted reaches the maxFiles limit.
maxfilesexceeded Called for each file that has been rejected because the number of files exceeds the maxFiles limit.
All of these receive a list of files as first parameter:
addedfiles See addedfile for description.
All of these receive a list of files as first parameter and are only called if the uploadMultiple option is true:
processingmultiple See processing for description.
sendingmultiple See sending for description.
successmultiple See success for description.
errormultiple See error for description.
completemultiple See complete for description.
canceledmultiple See canceled for description.
Special events:
totaluploadprogress Called with the total uploadProgress (0-100), the totalBytes and the totalBytesSent. This event can be used to show the overall upload progress of all files.
reset Called when all files in the list are removed and the dropzone is reset to initial state.
queuecomplete Called when all files in the queue finish uploading.


If you want to theme your Dropzone to look fully customized, in most cases you can simply replace the preview HTML template, adapt your CSS, and maybe create a few additional event listeners.

You will go very far with this approach. As an example, I created an example where I made Dropzone look and feel exactly the way jQuery File Uploader does with a few lines of configuration code. Check it out!

As you can see, the biggest change is the previewTemplate. I then added a few additional event listeners to make it look exactly like the reference.

You can however, implement your UI completely from scratch.

Dropzone itself sets up a lot of event listeners when a Dropzone is created, that handle all your UI. They do stuff like: create a new HTML element, add the <img> element when provided with image data (with the thumbnail event), update the progress bar when the uploadprogress event fires, show a checkmark when the success event fires, etc…

Everything visual is done in those event handlers. If you would overwrite all of them with empty functions, Dropzone would still be fully functional, but wouldn’t display the dropped files anymore.

If you like the default look of Dropzone, but would just like to add a few bells and whistles here and there, you should just add additional event listeners instead.

Overwriting the default event listeners, and creating your own, custom Dropzone, would look something like this:

// This is an example of completely disabling Dropzone's default behavior.
// Do *not* use this unless you really know what you are doing.
Dropzone.myDropzone.options = {
  previewTemplate: document.querySelector('#template-container').innerHTML,
  // Specifing an event as an configuration option overwrites the default
  // `addedfile` event handler.
  addedfile: function(file) {
    file.previewElement = Dropzone.createElement(this.options.previewTemplate);
    // Now attach this new element some where in your page
  thumbnail: function(file, dataUrl) {
    // Display the image in your file.previewElement
  uploadprogress: function(file, progress, bytesSent) {
    // Display the progress
  // etc...

Obviously this lacks the actual implementation. Look at the source to see how Dropzone does it internally.

You should use this option if you don’t need any of the default Dropzone UI, but are only interested in Dropzone for it’s event handlers, file upload and drag’n’drop functionality.


If you do not want the default message at all (»Drop files to upload (or click)«), you can put an element inside your dropzone element with the class dz-message and dropzone will not create the message for you.

Dropzone will submit any hidden fields you have in your dropzone form. So this is an easy way to submit additional data. You can also use the params option.

Dropzone adds data to the file object you can use when events fire. You can access file.width and file.height if it’s an image, as well as file.upload which is an object containing: progress (0-100), total (the total bytes) and bytesSent.

If you want to add additional data to the file upload that has to be specific for each file, you can register for the sending event:

myDropzone.on("sending", function(file, xhr, formData) {
  // Will send the filesize along with the file as POST data.
  formData.append("filesize", file.size);

To access the preview html of a file, you can access file.previewElement. For example:

myDropzone.on("addedfile", function(file) {
  file.previewElement.addEventListener("click", function() {

If you want the whole body to be a Dropzone and display the files somewhere else you can simply instantiate a Dropzone object for the body, and define the previewsContainer option. The previewsContainer should have the dropzone-previews or dropzone class to properly display the file previews.

new Dropzone(document.body, {
  previewsContainer: ".dropzone-previews",
  // You probably don't want the whole body
  // to be clickable to select files
  clickable: false

Look at the gitlab wiki for more examples.

If you have any problems using Dropzone, please try to find help on stackoverflow.com by using the dropzone.js tag. Only create an issue on GitLab when you think you found a bug or want to suggest a new feature.


This section describes compatibility with browsers and older versions of Dropzone.

Browser Support

For all the other browsers, dropzone provides an oldschool file input fallback.

There is no workaround for drag’n’drop in older browsers – it simply isn’t supported. The same goes for image previews, etc… But using dropzone, your users using an old browser will be able to upload files. It just won’t look and feel great. But hey, that’s their fault.

Version 5.0

Version 4.0

Version 3.0

Version 2.0

Starting with version 2.0, Dropzone no longer depends on jQuery, but Dropzone still registers itself as a jQuery module if available.

That means that creating your Dropzones like this still works:

$("#my-dropzone").dropzone({ /* options */ });

If you create your Dropzones with the normal constructor though, you have to pass either the raw HTMLElement, or a selector string. So those versions all work:

// With jQuery
new Dropzone($("#my-dropzone").get(0));
// Without jQuery
new Dropzone("#my-dropzone");
new Dropzone(document.querySelector("#my-dropzone"));

Another thing that changed, is that Dropzone no longer stores its instances inside the element’s data property. So to get a dropzone for an element do this now:

// DEPRECATED, do not use:
$("#my-dropzone").data("dropzone"); // won't work anymore
// Do this now:
Dropzone.forElement(element); // Providing a raw HTMLElement
// or
Dropzone.forElement("#my-dropzone"); // Providing a selector string.


Please consider donating if you like this project. I’ve put a lot of my free time into this project and donations help to justify it.

Use the Paypal button, tiptheweb or my Bitcoin address: