diff --git a/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-09-21.sql b/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-09-21.sql
new file mode 100644
index 0000000000000..4fd21a6975a28
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-09-21.sql
@@ -0,0 +1,2 @@
+INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
+(0, 'plg_captcha_hcaptcha', 'plugin', 'hcaptcha', 'captcha', 0, 0, 1, 0, 1, '', '{"publicKey":"","privateKey":"","theme":"light","size":"normal"}', '', 0, NULL, 0, 0);
diff --git a/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-09-21.sql b/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-09-21.sql
new file mode 100644
index 0000000000000..f8a56fb4cdd2b
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-09-21.sql
@@ -0,0 +1,2 @@
+INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
+(0, 'plg_captcha_hcaptcha', 'plugin', 'hcaptcha', 'captcha', 0, 0, 1, 0, 1, '', '{"publicKey":"","privateKey":"","theme":"light","size":"normal"}', '', 0, NULL, 0, 0);
diff --git a/administrator/language/en-GB/plg_captcha_hcaptcha.ini b/administrator/language/en-GB/plg_captcha_hcaptcha.ini
new file mode 100644
index 0000000000000..0025f18c1e387
--- /dev/null
+++ b/administrator/language/en-GB/plg_captcha_hcaptcha.ini
@@ -0,0 +1,33 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2020 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt
+; Note : All ini files need to be saved as UTF-8
+
+PLG_CAPTCHA_HCAPTCHA="CAPTCHA - hCaptcha"
+PLG_CAPTCHA_HCAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin uses the hCAPTCHA service to prevent spammers. To get a site and secret key for your domain, go to https://www.hcaptcha.com. To use this for new account registration, go to Options in the User Manager and select CAPTCHA - hCAPTCHA as the CAPTCHA."
+
+; Params
+PLG_CAPTCHA_HCAPTCHA_PUBLIC_KEY="Site Key"
+PLG_CAPTCHA_HCAPTCHA_PUBLIC_KEY_DESC="Site Keys are used to uniquely identify your site."
+PLG_CAPTCHA_HCAPTCHA_PRIVATE_KEY="Secret Key"
+PLG_CAPTCHA_HCAPTCHA_PRIVATE_KEY_DESC="A secret Key is used to verify your hCaptcha account."
+
+PLG_CAPTCHA_HCAPTCHA_THEME="Theme"
+PLG_CAPTCHA_HCAPTCHA_THEME_LIGHT="Light"
+PLG_CAPTCHA_HCAPTCHA_THEME_DARK="Dark"
+
+PLG_CAPTCHA_HCAPTCHA_SIZE="Size"
+PLG_CAPTCHA_HCAPTCHA_SIZE_NORMAL="Normal"
+PLG_CAPTCHA_HCAPTCHA_SIZE_COMPACT="Compact"
+
+; Privacy
+PLG_CAPTCHA_HCAPTCHA_PRIVACY_CAPABILITY_IP_ADDRESS="The hCaptcha plugin integrates with hcaptcha's CAPTCHA system as a spam protection service. As part of this service, the IP address of the user answering the captcha challenge is transmitted to hcaptcha.com."
+
+; Error messages
+PLG_CAPTCHA_HCAPTCHA_ERROR_CANT_CONNECT_TO_HCAPTCHA_SERVERS="Unable to connect to the hcaptcha.com servers"
+PLG_CAPTCHA_HCAPTCHA_ERROR_NO_PUBLIC_KEY="Public Key (Site Key) is missing"
+PLG_CAPTCHA_HCAPTCHA_ERROR_NO_PRIVATE_KEY="Private Key (Secret Key) is missing"
+PLG_CAPTCHA_HCAPTCHA_ERROR_NO_IP="Error: No IP address"
+PLG_CAPTCHA_HCAPTCHA_ERROR_EMPTY_SOLUTION="Please complete the CAPTCHA"
+PLG_CAPTCHA_HCAPTCHA_ERROR_INCORRECT_CAPTCHA="The CAPTCHA was incorrect"
+PLG_CAPTCHA_HCAPTCHA_ERROR_INVALID_RESPONSE="Invalid response from hcaptcha.com"
diff --git a/administrator/language/en-GB/plg_captcha_hcaptcha.sys.ini b/administrator/language/en-GB/plg_captcha_hcaptcha.sys.ini
new file mode 100644
index 0000000000000..f464b03294455
--- /dev/null
+++ b/administrator/language/en-GB/plg_captcha_hcaptcha.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2020 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt
+; Note : All ini files need to be saved as UTF-8
+
+PLG_CAPTCHA_HCAPTCHA="CAPTCHA - hCaptcha"
+PLG_CAPTCHA_HCAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin uses the hCAPTCHA service to prevent spammers. To get a site and secret key for your domain, go to https://www.hcaptcha.com. To use this for new account registration, go to Options in the User Manager and select CAPTCHA - hCAPTCHA as the CAPTCHA."
diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql
index 677625d971ce3..925f508ec3f68 100644
--- a/installation/sql/mysql/base.sql
+++ b/installation/sql/mysql/base.sql
@@ -270,6 +270,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`,
(0, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 0, 0),
(0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 0, 0),
(0, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 0, 0),
+(0, 'plg_captcha_hcaptcha', 'plugin', 'hcaptcha', 'captcha', 0, 0, 1, 0, 1, '', '{"publicKey":"","privateKey":"","theme":"light","size":"normal"}', '', 0, 0),
(0, 'plg_captcha_recaptcha', 'plugin', 'recaptcha', 'captcha', 0, 0, 1, 0, 1, '', '{"public_key":"","private_key":"","theme":"clean"}', '', 0, 0),
(0, 'plg_system_highlight', 'plugin', 'highlight', 'system', 0, 1, 1, 0, 1, '', '', '', 7, 0),
(0, 'plg_content_finder', 'plugin', 'finder', 'content', 0, 1, 1, 0, 1, '', '', '', 0, 0),
diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql
index 259b9df2f5f93..d354cebbc9298 100644
--- a/installation/sql/postgresql/base.sql
+++ b/installation/sql/postgresql/base.sql
@@ -276,6 +276,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder",
(0, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 0, 0),
(0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 0, 0),
(0, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 0, 0),
+(0, 'plg_captcha_hcaptcha', 'plugin', 'hcaptcha', 'captcha', 0, 0, 1, 0, 1, '', '{"publicKey":"","privateKey":"","theme":"light","size":"normal"}', '', 0, 0),
(0, 'plg_captcha_recaptcha', 'plugin', 'recaptcha', 'captcha', 0, 0, 1, 0, 1, '', '{"public_key":"","private_key":"","theme":"clean"}', '', 0, 0),
(0, 'plg_system_highlight', 'plugin', 'highlight', 'system', 0, 1, 1, 0, 1, '', '', '', 7, 0),
(0, 'plg_content_finder', 'plugin', 'finder', 'content', 0, 1, 1, 0, 1, '', '', '', 0, 0),
diff --git a/plugins/captcha/hcaptcha/hcaptcha.php b/plugins/captcha/hcaptcha/hcaptcha.php
new file mode 100644
index 0000000000000..2c688d343ccc4
--- /dev/null
+++ b/plugins/captcha/hcaptcha/hcaptcha.php
@@ -0,0 +1,160 @@
+ array(
+ Text::_('PLG_CAPTCHA_HCAPTCHA_PRIVACY_CAPABILITY_IP_ADDRESS'),
+ )
+ );
+ }
+
+ /**
+ * Initialise the captcha
+ *
+ * @return boolean True on success, false otherwise
+ *
+ * @since 4.0.0
+ * @throws Exception
+ */
+ public function onInit()
+ {
+ // If there is no Public Key set, then this plugin is no use, so exit
+ if ($this->params->get('publicKey', '') === '')
+ {
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_NO_PUBLIC_KEY'));
+ }
+
+ // Load the JavaScript from hCaptcha
+ Factory::getApplication()->getDocument()->getWebAssetManager()->registerAndUseScript(
+ 'plg_captcha_hcaptcha.api', 'https://hcaptcha.com/1/api.js', [], ['defer' => true]
+ );
+
+ return true;
+ }
+
+ /**
+ * Gets the challenge HTML
+ *
+ * @param string $name The name of the field. Not Used.
+ * @param string $id The id of the field.
+ * @param string $class The class of the field.
+ *
+ * @return string The HTML to be embedded in the form.
+ *
+ * @since 4.0.0
+ */
+ public function onDisplay($name = null, $id = 'hcaptcha', $class = '')
+ {
+ $dom = new \DOMDocument('1.0', 'UTF-8');
+ $ele = $dom->createElement('div');
+ $ele->setAttribute('id', $id);
+ $ele->setAttribute('class', 'h-captcha');
+ $ele->setAttribute('data-sitekey', $this->params->get('publicKey', ''));
+ $ele->setAttribute('data-theme', $this->params->get('theme', 'light'));
+ $ele->setAttribute('data-size', $this->params->get('size', 'normal'));
+
+ $dom->appendChild($ele);
+
+ return $dom->saveHTML($ele);
+ }
+
+ /**
+ * Calls an HTTP POST function to verify if the user's guess was correct
+ *
+ * @param string $code Answer provided by user. Not needed for the Hcaptcha implementation
+ *
+ * @return boolean
+ * @since 4.0.0
+ * @throws Exception
+ */
+ public function onCheckAnswer($code = null)
+ {
+ $input = Factory::getApplication()->input;
+ $privateKey = $this->params->get('privateKey');
+ $remoteIp = IpHelper::getIp();
+ $hCaptchaResponse = $code ?? $input->get('h-captcha-response', '', 'cmd');
+
+ // Check for Private Key
+ if (empty($privateKey))
+ {
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_NO_PRIVATE_KEY'));
+ }
+
+ // Check for IP
+ if (empty($remoteIp))
+ {
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_NO_IP'));
+ }
+
+ if (empty($hCaptchaResponse))
+ {
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_EMPTY_SOLUTION'));
+ }
+
+ try
+ {
+ $verifyResponse = HttpFactory::getHttp()->get(
+ 'https://hcaptcha.com/siteverify?secret=' . $privateKey .
+ '&response=' . $hCaptchaResponse .
+ '&remoteip=' . $remoteIp
+ );
+ }
+ catch (RuntimeException $e)
+ {
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_CANT_CONNECT_TO_HCAPTCHA_SERVERS'));
+ }
+
+ if ($verifyResponse->code !== 200 || $verifyResponse->body === '')
+ {
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_INVALID_RESPONSE'));
+ }
+
+ $responseData = json_decode($verifyResponse->body);
+
+ if ($responseData->success)
+ {
+ return true;
+ }
+
+ throw new \RuntimeException(Text::_('PLG_CAPTCHA_HCAPTCHA_ERROR_INCORRECT_CAPTCHA'));
+ }
+}
diff --git a/plugins/captcha/hcaptcha/hcaptcha.xml b/plugins/captcha/hcaptcha/hcaptcha.xml
new file mode 100644
index 0000000000000..746ccb4920320
--- /dev/null
+++ b/plugins/captcha/hcaptcha/hcaptcha.xml
@@ -0,0 +1,67 @@
+
+
+ plg_captcha_hcaptcha
+ 1.0.0
+ April 2020
+ Joomla! Project
+ admin@joomla.org
+ www.joomla.org
+ Copyright (C) 2005 - 2019 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ PLG_CAPTCHA_HCAPTCHA_XML_DESCRIPTION
+
+ hcaptcha.php
+ language
+
+
+ plg_captcha_hcaptcha.ini
+ plg_captcha_hcaptcha.sys.ini
+
+
+
+
+
+
+