diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php
index 351e064595b0debdfdae2738f8b60ceca80af288..918b4eb2255b766f20324cde334abdc6ed87da0b 100644
--- a/apps/dav/lib/CardDAV/AddressBookImpl.php
+++ b/apps/dav/lib/CardDAV/AddressBookImpl.php
@@ -97,20 +97,22 @@ class AddressBookImpl implements IAddressBook {
 	/**
 	 * @param string $pattern which should match within the $searchProperties
 	 * @param array $searchProperties defines the properties within the query pattern should match
-	 * @param array $options Options to define the output format
-	 * 	- types boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array
+	 * @param array $options Options to define the output format and search behavior
+	 * 	- 'types' boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array
 	 *    example: ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['type => 'HOME', 'value' => 'g@h.i']]
+	 * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
 	 * @return array an array of contacts which are arrays of key-value-pairs
 	 *  example result:
 	 *  [
 	 *		['id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'],
 	 *		['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['d@e.f', 'g@h.i']]
 	 *	]
+	 * @param array $options = array() 'escape_like_param' - to not escape wildcards _ and % - for future use. One should always have options!
 	 * @return array an array of contacts which are arrays of key-value-pairs
 	 * @since 5.0.0
 	 */
 	public function search($pattern, $searchProperties, $options) {
-		$results = $this->backend->search($this->getKey(), $pattern, $searchProperties);
+		$results = $this->backend->search($this->getKey(), $pattern, $searchProperties, $options = $options);
 
 		$withTypes = \array_key_exists('types', $options) && $options['types'] === true;
 
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index b16bcd993cf4354e914fd6f737e216d6c59a8360..7dbd41a69c8cf7e143eeb4ef65a4901b94fe3cdc 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -903,9 +903,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 	 * @param int $addressBookId
 	 * @param string $pattern which should match within the $searchProperties
 	 * @param array $searchProperties defines the properties within the query pattern should match
+	 * @param array $options = array() to define the search behavior
+	 * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped, otherwise they are
 	 * @return array an array of contacts which are arrays of key-value-pairs
 	 */
-	public function search($addressBookId, $pattern, $searchProperties) {
+	public function search($addressBookId, $pattern, $searchProperties, $options = array()) {
 		$query = $this->db->getQueryBuilder();
 		$query2 = $this->db->getQueryBuilder();
 
@@ -919,7 +921,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 
 		// No need for like when the pattern is empty
 		if ('' !== $pattern) {
-			$query2->andWhere($query2->expr()->ilike('cp.value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%')));
+			if(\array_key_exists('escape_like_param', $options) && $options['escape_like_param'] === false) {
+				$query2->andWhere($query2->expr()->ilike('cp.value', $query->createNamedParameter($pattern)));
+			} else {
+				$query2->andWhere($query2->expr()->ilike('cp.value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($pattern) . '%')));
+			}
 		}
 
 		$query->select('c.carddata', 'c.uri')->from($this->dbCardsTable, 'c')
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
index 86c85a972e34f731cea07682902d0b05ef667b21..531f50e96c2368104a9b4d83eb5a87d766b77c78 100644
--- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
@@ -642,22 +642,27 @@ class CardDavBackendTest extends TestCase {
 	 *
 	 * @param string $pattern
 	 * @param array $properties
+	 * @param array $options
 	 * @param array $expected
 	 */
-	public function testSearch($pattern, $properties, $expected) {
+	public function testSearch($pattern, $properties, $options, $expected) {
 		/** @var VCard $vCards */
 		$vCards = [];
 		$vCards[0] = new VCard();
 		$vCards[0]->add(new Text($vCards[0], 'UID', 'uid'));
 		$vCards[0]->add(new Text($vCards[0], 'FN', 'John Doe'));
-		$vCards[0]->add(new Text($vCards[0], 'CLOUD', 'john@owncloud.org'));
+		$vCards[0]->add(new Text($vCards[0], 'CLOUD', 'john@nextcloud.com'));
 		$vCards[1] = new VCard();
 		$vCards[1]->add(new Text($vCards[1], 'UID', 'uid'));
 		$vCards[1]->add(new Text($vCards[1], 'FN', 'John M. Doe'));
+		$vCards[2] = new VCard();
+		$vCards[2]->add(new Text($vCards[2], 'UID', 'uid'));
+		$vCards[2]->add(new Text($vCards[2], 'FN', 'find without options'));
+		$vCards[2]->add(new Text($vCards[2], 'CLOUD', 'peter_pan@nextcloud.com'));
 
 		$vCardIds = [];
 		$query = $this->db->getQueryBuilder();
-		for($i=0; $i<2; $i++) {
+		for($i=0; $i < 3; $i++) {
 			$query->insert($this->dbCardsTable)
 					->values(
 							[
@@ -690,7 +695,7 @@ class CardDavBackendTest extends TestCase {
 								'addressbookid' => $query->createNamedParameter(0),
 								'cardid' => $query->createNamedParameter($vCardIds[0]),
 								'name' => $query->createNamedParameter('CLOUD'),
-								'value' => $query->createNamedParameter('John@owncloud.org'),
+								'value' => $query->createNamedParameter('John@nextcloud.com'),
 								'preferred' => $query->createNamedParameter(0)
 						]
 				);
@@ -706,8 +711,30 @@ class CardDavBackendTest extends TestCase {
 				]
 			);
 		$query->execute();
+		$query->insert($this->dbCardsPropertiesTable)
+			->values(
+				[
+					'addressbookid' => $query->createNamedParameter(0),
+					'cardid' => $query->createNamedParameter($vCardIds[2]),
+					'name' => $query->createNamedParameter('FN'),
+					'value' => $query->createNamedParameter('find without options'),
+					'preferred' => $query->createNamedParameter(0)
+				]
+			);
+		$query->execute();
+		$query->insert($this->dbCardsPropertiesTable)
+			->values(
+				[
+					'addressbookid' => $query->createNamedParameter(0),
+					'cardid' => $query->createNamedParameter($vCardIds[2]),
+					'name' => $query->createNamedParameter('CLOUD'),
+					'value' => $query->createNamedParameter('peter_pan@nextcloud.com'),
+					'preferred' => $query->createNamedParameter(0)
+				]
+			);
+		$query->execute();
 
-		$result = $this->backend->search(0, $pattern, $properties);
+		$result = $this->backend->search(0, $pattern, $properties, $options);
 
 		// check result
 		$this->assertSame(count($expected), count($result));
@@ -726,11 +753,13 @@ class CardDavBackendTest extends TestCase {
 
 	public function dataTestSearch() {
 		return [
-				['John', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
-				['M. Doe', ['FN'], [['uri1', 'John M. Doe']]],
-				['Do', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
-				'check if duplicates are handled correctly' => ['John', ['FN', 'CLOUD'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
-				'case insensitive' => ['john', ['FN'], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]]
+				['John', ['FN'], [], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
+				['M. Doe', ['FN'], [], [['uri1', 'John M. Doe']]],
+				['Do', ['FN'], [], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
+				'check if duplicates are handled correctly' => ['John', ['FN', 'CLOUD'], [], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
+				'case insensitive' => ['john', ['FN'], [], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
+				'find "_" escaped' => ['_', ['CLOUD'], [], [['uri2', 'find without options']]],
+				'find not empty ClOUD' => ['%_%', ['CLOUD'], ['escape_like_param'=>false], [['uri0', 'John Doe'], ['uri2', 'find without options']]],
 		];
 	}
 
diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php
index e279997e634cfa6c241280d5f33d35ed746edd03..4a36f00de5647ec60a6ac8321be7ca9511706b75 100644
--- a/lib/private/ContactsManager.php
+++ b/lib/private/ContactsManager.php
@@ -35,7 +35,8 @@ namespace OC {
 		 *
 		 * @param string $pattern which should match within the $searchProperties
 		 * @param array $searchProperties defines the properties within the query pattern should match
-		 * @param array $options - for future use. One should always have options!
+		 * @param array $options = array() to define the search behavior
+		 * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
 		 * @return array an array of contacts which are arrays of key-value-pairs
 		 */
 		public function search($pattern, $searchProperties = array(), $options = array()) {
diff --git a/lib/public/Contacts/IManager.php b/lib/public/Contacts/IManager.php
index e744a92d9e29811c2b7d5435cb03919c0d97c992..84948a929c0fd8df6302ec98a8cde1eb1a26b6ad 100644
--- a/lib/public/Contacts/IManager.php
+++ b/lib/public/Contacts/IManager.php
@@ -90,7 +90,8 @@ interface IManager {
 	 *
 	 * @param string $pattern which should match within the $searchProperties
 	 * @param array $searchProperties defines the properties within the query pattern should match
-	 * @param array $options - for future use. One should always have options!
+	 * @param array $options = array() to define the search behavior
+	 * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
 	 * @return array an array of contacts which are arrays of key-value-pairs
 	 * @since 6.0.0
 	 */