diff --git a/daemon.py b/daemon.py
index ee6625ad..fdc9a0ea 100644
--- a/daemon.py
+++ b/daemon.py
@@ -2140,6 +2140,234 @@ class PubServer(BaseHTTPRequestHandler):
                                cookie, callingDomain)
         self.server.POSTbusy = False
 
+    def _receiveSearchQuery(self, callingDomain: str, cookie: str,
+                            authorized: bool, path: str,
+                            baseDir: str, httpPrefix: str,
+                            domain: str, domainFull: str,
+                            port: int, searchForEmoji: bool,
+                            onionDomain: str, i2pDomain: str, debug: bool):
+        """Receive a search query
+        """
+        # get the page number
+        pageNumber = 1
+        if '/searchhandle?page=' in path:
+            pageNumberStr = path.split('/searchhandle?page=')[1]
+            if '#' in pageNumberStr:
+                pageNumberStr = pageNumberStr.split('#')[0]
+            if pageNumberStr.isdigit():
+                pageNumber = int(pageNumberStr)
+            path = path.split('?page=')[0]
+
+        usersPath = path.replace('/searchhandle', '')
+        actorStr = httpPrefix + '://' + domainFull + usersPath
+        length = int(self.headers['Content-length'])
+        try:
+            searchParams = self.rfile.read(length).decode('utf-8')
+        except SocketError as e:
+            if e.errno == errno.ECONNRESET:
+                print('WARN: POST searchParams connection was reset')
+            else:
+                print('WARN: POST searchParams socket error')
+            self.send_response(400)
+            self.end_headers()
+            self.server.POSTbusy = False
+            return
+        except ValueError as e:
+            print('ERROR: POST searchParams rfile.read failed')
+            print(e)
+            self.send_response(400)
+            self.end_headers()
+            self.server.POSTbusy = False
+            return
+        if 'submitBack=' in searchParams:
+            # go back on search screen
+            if callingDomain.endswith('.onion') and onionDomain:
+                actorStr = 'http://' + onionDomain + usersPath
+            elif (callingDomain.endswith('.i2p') and i2pDomain):
+                actorStr = 'http://' + i2pDomain + usersPath
+            self._redirect_headers(actorStr + '/' +
+                                   self.server.defaultTimeline,
+                                   cookie, callingDomain)
+            self.server.POSTbusy = False
+            return
+        if 'searchtext=' in searchParams:
+            searchStr = searchParams.split('searchtext=')[1]
+            if '&' in searchStr:
+                searchStr = searchStr.split('&')[0]
+            searchStr = \
+                urllib.parse.unquote_plus(searchStr.strip())
+            searchStr2 = searchStr.lower().strip('\n').strip('\r')
+            print('searchStr: ' + searchStr)
+            if searchForEmoji:
+                searchStr = ':' + searchStr + ':'
+            if searchStr.startswith('#'):
+                nickname = getNicknameFromActor(actorStr)
+                # hashtag search
+                hashtagStr = \
+                    htmlHashtagSearch(nickname,
+                                      domain,
+                                      port,
+                                      self.server.recentPostsCache,
+                                      self.server.maxRecentPosts,
+                                      self.server.translate,
+                                      baseDir,
+                                      searchStr[1:], 1,
+                                      maxPostsInFeed,
+                                      self.server.session,
+                                      self.server.cachedWebfingers,
+                                      self.server.personCache,
+                                      httpPrefix,
+                                      self.server.projectVersion,
+                                      self.server.YTReplacementDomain)
+                if hashtagStr:
+                    msg = hashtagStr.encode('utf-8')
+                    self._login_headers('text/html',
+                                        len(msg), callingDomain)
+                    self._write(msg)
+                    self.server.POSTbusy = False
+                    return
+            elif searchStr.startswith('*'):
+                # skill search
+                searchStr = searchStr.replace('*', '').strip()
+                skillStr = \
+                    htmlSkillsSearch(self.server.translate,
+                                     baseDir,
+                                     httpPrefix,
+                                     searchStr,
+                                     self.server.instanceOnlySkillsSearch,
+                                     64)
+                if skillStr:
+                    msg = skillStr.encode('utf-8')
+                    self._login_headers('text/html',
+                                        len(msg), callingDomain)
+                    self._write(msg)
+                    self.server.POSTbusy = False
+                    return
+            elif searchStr.startswith('!'):
+                # your post history search
+                nickname = getNicknameFromActor(actorStr)
+                searchStr = searchStr.replace('!', '').strip()
+                historyStr = \
+                    htmlHistorySearch(self.server.translate,
+                                      baseDir,
+                                      httpPrefix,
+                                      nickname,
+                                      domain,
+                                      searchStr,
+                                      maxPostsInFeed,
+                                      pageNumber,
+                                      self.server.projectVersion,
+                                      self.server.recentPostsCache,
+                                      self.server.maxRecentPosts,
+                                      self.server.session,
+                                      self.server.cachedWebfingers,
+                                      self.server.personCache,
+                                      port,
+                                      self.server.YTReplacementDomain)
+                if historyStr:
+                    msg = historyStr.encode('utf-8')
+                    self._login_headers('text/html',
+                                        len(msg), callingDomain)
+                    self._write(msg)
+                    self.server.POSTbusy = False
+                    return
+            elif ('@' in searchStr or
+                  ('://' in searchStr and
+                   ('/users/' in searchStr or
+                    '/profile/' in searchStr or
+                    '/accounts/' in searchStr or
+                    '/channel/' in searchStr))):
+                # profile search
+                nickname = getNicknameFromActor(actorStr)
+                if not self.server.session:
+                    print('Starting new session during handle search')
+                    self.server.session = \
+                        createSession(self.server.proxyType)
+                    if not self.server.session:
+                        print('ERROR: POST failed to create session ' +
+                              'during handle search')
+                        self._404()
+                        self.server.POSTbusy = False
+                        return
+                profilePathStr = self.path.replace('/searchhandle', '')
+                profileStr = \
+                    htmlProfileAfterSearch(self.server.recentPostsCache,
+                                           self.server.maxRecentPosts,
+                                           self.server.translate,
+                                           baseDir,
+                                           profilePathStr,
+                                           httpPrefix,
+                                           nickname,
+                                           domain,
+                                           port,
+                                           searchStr,
+                                           self.server.session,
+                                           self.server.cachedWebfingers,
+                                           self.server.personCache,
+                                           self.server.debug,
+                                           self.server.projectVersion,
+                                           self.server.YTReplacementDomain)
+                if profileStr:
+                    msg = profileStr.encode('utf-8')
+                    self._login_headers('text/html',
+                                        len(msg), callingDomain)
+                    self._write(msg)
+                    self.server.POSTbusy = False
+                    return
+                else:
+                    if callingDomain.endswith('.onion') and onionDomain:
+                        actorStr = 'http://' + onionDomain + usersPath
+                    elif (callingDomain.endswith('.i2p') and i2pDomain):
+                        actorStr = 'http://' + i2pDomain + usersPath
+                    self._redirect_headers(actorStr + '/search',
+                                           cookie, callingDomain)
+                    self.server.POSTbusy = False
+                    return
+            elif (searchStr.startswith(':') or
+                  searchStr2.endswith(' emoji')):
+                # eg. "cat emoji"
+                if searchStr2.endswith(' emoji'):
+                    searchStr = \
+                        searchStr2.replace(' emoji', '')
+                # emoji search
+                emojiStr = \
+                    htmlSearchEmoji(self.server.translate,
+                                    baseDir,
+                                    httpPrefix,
+                                    searchStr)
+                if emojiStr:
+                    msg = emojiStr.encode('utf-8')
+                    self._login_headers('text/html',
+                                        len(msg), callingDomain)
+                    self._write(msg)
+                    self.server.POSTbusy = False
+                    return
+            else:
+                # shared items search
+                sharedItemsStr = \
+                    htmlSearchSharedItems(self.server.translate,
+                                          baseDir,
+                                          searchStr, pageNumber,
+                                          maxPostsInFeed,
+                                          httpPrefix,
+                                          domainFull,
+                                          actorStr, callingDomain)
+                if sharedItemsStr:
+                    msg = sharedItemsStr.encode('utf-8')
+                    self._login_headers('text/html',
+                                        len(msg), callingDomain)
+                    self._write(msg)
+                    self.server.POSTbusy = False
+                    return
+        if callingDomain.endswith('.onion') and onionDomain:
+            actorStr = 'http://' + onionDomain + usersPath
+        elif callingDomain.endswith('.i2p') and i2pDomain:
+            actorStr = 'http://' + i2pDomain + usersPath
+        self._redirect_headers(actorStr + '/' +
+                               self.server.defaultTimeline,
+                               cookie, callingDomain)
+        self.server.POSTbusy = False
+
     def _receiveVote(self, callingDomain: str, cookie: str,
                      authorized: bool, path: str,
                      baseDir: str, httpPrefix: str,
@@ -8905,233 +9133,17 @@ class PubServer(BaseHTTPRequestHandler):
         if ((authorized or searchForEmoji) and
             (self.path.endswith('/searchhandle') or
              '/searchhandle?page=' in self.path)):
-            # get the page number
-            pageNumber = 1
-            if '/searchhandle?page=' in self.path:
-                pageNumberStr = self.path.split('/searchhandle?page=')[1]
-                if '#' in pageNumberStr:
-                    pageNumberStr = pageNumberStr.split('#')[0]
-                if pageNumberStr.isdigit():
-                    pageNumber = int(pageNumberStr)
-                self.path = self.path.split('?page=')[0]
-
-            usersPath = self.path.replace('/searchhandle', '')
-            actorStr = \
-                self.server.httpPrefix + '://' + \
-                self.server.domainFull + usersPath
-            length = int(self.headers['Content-length'])
-            try:
-                searchParams = self.rfile.read(length).decode('utf-8')
-            except SocketError as e:
-                if e.errno == errno.ECONNRESET:
-                    print('WARN: POST searchParams connection was reset')
-                else:
-                    print('WARN: POST searchParams socket error')
-                self.send_response(400)
-                self.end_headers()
-                self.server.POSTbusy = False
-                return
-            except ValueError as e:
-                print('ERROR: POST searchParams rfile.read failed')
-                print(e)
-                self.send_response(400)
-                self.end_headers()
-                self.server.POSTbusy = False
-                return
-            if 'submitBack=' in searchParams:
-                # go back on search screen
-                if callingDomain.endswith('.onion') and \
-                   self.server.onionDomain:
-                    actorStr = 'http://' + self.server.onionDomain + usersPath
-                elif (callingDomain.endswith('.i2p') and
-                      self.server.i2pDomain):
-                    actorStr = 'http://' + self.server.i2pDomain + usersPath
-                self._redirect_headers(actorStr + '/' +
-                                       self.server.defaultTimeline,
-                                       cookie, callingDomain)
-                self.server.POSTbusy = False
-                return
-            if 'searchtext=' in searchParams:
-                searchStr = searchParams.split('searchtext=')[1]
-                if '&' in searchStr:
-                    searchStr = searchStr.split('&')[0]
-                searchStr = \
-                    urllib.parse.unquote_plus(searchStr.strip())
-                searchStr2 = searchStr.lower().strip('\n').strip('\r')
-                print('searchStr: ' + searchStr)
-                if searchForEmoji:
-                    searchStr = ':' + searchStr + ':'
-                if searchStr.startswith('#'):
-                    nickname = getNicknameFromActor(actorStr)
-                    # hashtag search
-                    hashtagStr = \
-                        htmlHashtagSearch(nickname,
-                                          self.server.domain,
-                                          self.server.port,
-                                          self.server.recentPostsCache,
-                                          self.server.maxRecentPosts,
-                                          self.server.translate,
-                                          self.server.baseDir,
-                                          searchStr[1:], 1,
-                                          maxPostsInFeed,
-                                          self.server.session,
-                                          self.server.cachedWebfingers,
-                                          self.server.personCache,
-                                          self.server.httpPrefix,
-                                          self.server.projectVersion,
-                                          self.server.YTReplacementDomain)
-                    if hashtagStr:
-                        msg = hashtagStr.encode('utf-8')
-                        self._login_headers('text/html',
-                                            len(msg), callingDomain)
-                        self._write(msg)
-                        self.server.POSTbusy = False
-                        return
-                elif searchStr.startswith('*'):
-                    # skill search
-                    searchStr = searchStr.replace('*', '').strip()
-                    skillStr = \
-                        htmlSkillsSearch(self.server.translate,
-                                         self.server.baseDir,
-                                         self.server.httpPrefix,
-                                         searchStr,
-                                         self.server.instanceOnlySkillsSearch,
-                                         64)
-                    if skillStr:
-                        msg = skillStr.encode('utf-8')
-                        self._login_headers('text/html',
-                                            len(msg), callingDomain)
-                        self._write(msg)
-                        self.server.POSTbusy = False
-                        return
-                elif searchStr.startswith('!'):
-                    # your post history search
-                    nickname = getNicknameFromActor(actorStr)
-                    searchStr = searchStr.replace('!', '').strip()
-                    historyStr = \
-                        htmlHistorySearch(self.server.translate,
-                                          self.server.baseDir,
-                                          self.server.httpPrefix,
-                                          nickname,
-                                          self.server.domain,
-                                          searchStr,
-                                          maxPostsInFeed,
-                                          pageNumber,
-                                          self.server.projectVersion,
-                                          self.server.recentPostsCache,
-                                          self.server.maxRecentPosts,
-                                          self.server.session,
-                                          self.server.cachedWebfingers,
-                                          self.server.personCache,
-                                          self.server.port,
-                                          self.server.YTReplacementDomain)
-                    if historyStr:
-                        msg = historyStr.encode('utf-8')
-                        self._login_headers('text/html',
-                                            len(msg), callingDomain)
-                        self._write(msg)
-                        self.server.POSTbusy = False
-                        return
-                elif ('@' in searchStr or
-                      ('://' in searchStr and
-                       ('/users/' in searchStr or
-                        '/profile/' in searchStr or
-                        '/accounts/' in searchStr or
-                        '/channel/' in searchStr))):
-                    # profile search
-                    nickname = getNicknameFromActor(actorStr)
-                    if not self.server.session:
-                        print('Starting new session during handle search')
-                        self.server.session = \
-                            createSession(self.server.proxyType)
-                        if not self.server.session:
-                            print('ERROR: POST failed to create session ' +
-                                  'during handle search')
-                            self._404()
-                            self.server.POSTbusy = False
-                            return
-                    profilePathStr = self.path.replace('/searchhandle', '')
-                    profileStr = \
-                        htmlProfileAfterSearch(self.server.recentPostsCache,
-                                               self.server.maxRecentPosts,
-                                               self.server.translate,
-                                               self.server.baseDir,
-                                               profilePathStr,
-                                               self.server.httpPrefix,
-                                               nickname,
-                                               self.server.domain,
-                                               self.server.port,
-                                               searchStr,
-                                               self.server.session,
-                                               self.server.cachedWebfingers,
-                                               self.server.personCache,
-                                               self.server.debug,
-                                               self.server.projectVersion,
-                                               self.server.YTReplacementDomain)
-                    if profileStr:
-                        msg = profileStr.encode('utf-8')
-                        self._login_headers('text/html',
-                                            len(msg), callingDomain)
-                        self._write(msg)
-                        self.server.POSTbusy = False
-                        return
-                    else:
-                        if callingDomain.endswith('.onion') and \
-                           self.server.onionDomain:
-                            actorStr = 'http://' + self.server.onionDomain + \
-                                usersPath
-                        elif (callingDomain.endswith('.i2p') and
-                              self.server.i2pDomain):
-                            actorStr = 'http://' + self.server.i2pDomain + \
-                                usersPath
-                        self._redirect_headers(actorStr + '/search',
-                                               cookie, callingDomain)
-                        self.server.POSTbusy = False
-                        return
-                elif (searchStr.startswith(':') or
-                      searchStr2.endswith(' emoji')):
-                    # eg. "cat emoji"
-                    if searchStr2.endswith(' emoji'):
-                        searchStr = \
-                            searchStr2.replace(' emoji', '')
-                    # emoji search
-                    emojiStr = \
-                        htmlSearchEmoji(self.server.translate,
-                                        self.server.baseDir,
-                                        self.server.httpPrefix,
-                                        searchStr)
-                    if emojiStr:
-                        msg = emojiStr.encode('utf-8')
-                        self._login_headers('text/html',
-                                            len(msg), callingDomain)
-                        self._write(msg)
-                        self.server.POSTbusy = False
-                        return
-                else:
-                    # shared items search
-                    sharedItemsStr = \
-                        htmlSearchSharedItems(self.server.translate,
-                                              self.server.baseDir,
-                                              searchStr, pageNumber,
-                                              maxPostsInFeed,
-                                              self.server.httpPrefix,
-                                              self.server.domainFull,
-                                              actorStr, callingDomain)
-                    if sharedItemsStr:
-                        msg = sharedItemsStr.encode('utf-8')
-                        self._login_headers('text/html',
-                                            len(msg), callingDomain)
-                        self._write(msg)
-                        self.server.POSTbusy = False
-                        return
-            if callingDomain.endswith('.onion') and self.server.onionDomain:
-                actorStr = 'http://' + self.server.onionDomain + usersPath
-            elif callingDomain.endswith('.i2p') and self.server.i2pDomain:
-                actorStr = 'http://' + self.server.i2pDomain + usersPath
-            self._redirect_headers(actorStr + '/' +
-                                   self.server.defaultTimeline,
-                                   cookie, callingDomain)
-            self.server.POSTbusy = False
+            self._receiveSearchQuery(callingDomain, cookie,
+                                     authorized, self.path,
+                                     self.server.baseDir,
+                                     self.server.httpPrefix,
+                                     self.server.domain,
+                                     self.server.domainFull,
+                                     self.server.port,
+                                     searchForEmoji,
+                                     self.server.onionDomain,
+                                     self.server.i2pDomain,
+                                     self.server.debug)
             return
 
         self._benchmarkPOSTtimings(POSTstartTime, POSTtimings, 7)