Désactiver la recherche dans WordPress : sans plugin, avec functions.php (formulaire, ?s=, REST)

Le code complet pour désactiver la recherche WordPress sans plugin : renvoyer une 404 sur les URL ?s=, retirer le formulaire, le widget et le bloc de recherche, fermer le point d’accès REST, et la variante .htaccess.

Comment désactiver le moteur de recherche dans WordPress
Réponse rapide

Ajoutez dans le fichier functions.php de votre thème un filtre sur parse_query qui transforme toute requête de recherche en 404, un filtre get_search_form qui renvoie une chaîne vide, et retirez le widget et le bloc de recherche. Le code complet, testé sur WordPress 7.1, est dans l’article, aucun plugin n’est nécessaire.

Un site vitrine de cinq pages, un site one-page, un portfolio : la recherche WordPress n’y sert à rien, et son formulaire encombre le thème. Pire, la page de résultats existe même sans formulaire, à l’adresse /?s=mot, et elle expose une page vide ou une liste de contenus que vous ne vouliez pas mettre en avant. Voici comment désactiver complètement la recherche dans WordPress, sans plugin, avec un extrait pour functions.php.

Pourquoi désactiver la recherche

  • Elle est inutile sur un petit site : tout est accessible depuis le menu en un clic.
  • Elle produit des pages de résultats sans valeur, que des robots peuvent solliciter avec n’importe quel mot, ce qui gaspille des ressources serveur et crée des URL parasites.
  • Le formulaire imposé par le thème n’a souvent pas sa place dans la maquette.

Le code complet pour functions.php

À placer dans le fichier functions.php de votre thème enfant (ou dans un petit plugin maison, pour survivre aux changements de thème). Chaque bloc ferme une porte différente.

functions.php
<?php
/**
 * Désactive la recherche WordPress côté public.
 */

// 1. Toute recherche par URL (/?s=mot ou /search/mot/) devient une page 404.
add_action( 'parse_query', function ( WP_Query $query ) {
    if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
        return;
    }
    $query->is_search = false;
    $query->set_404();
    status_header( 404 );
    nocache_headers();
} );

// 2. Le formulaire de recherche du thème n'est plus affiché.
add_filter( 'get_search_form', '__return_empty_string' );

// 3. Le widget de recherche classique est retiré.
add_action( 'widgets_init', function () {
    unregister_widget( 'WP_Widget_Search' );
}, 11 );

// 4. Le bloc « Recherche » de l'éditeur disparaît du menu d'insertion.
add_filter( 'allowed_block_types_all', function ( $allowed ) {
    if ( ! is_array( $allowed ) ) {
        $registry = WP_Block_Type_Registry::get_instance();
        $allowed  = array_keys( $registry->get_all_registered() );
    }
    return array_values( array_diff( $allowed, [ 'core/search' ] ) );
} );

// 5. Le point d'accès REST de recherche est fermé.
add_filter( 'rest_endpoints', function ( array $endpoints ) {
    unset( $endpoints['/wp/v2/search'], $endpoints['/wp/v2/search/(?P<id>[\d]+)'] );
    return $endpoints;
} );

Ce que fait chaque bloc :

  1. La requête. Sur parse_query, si la requête principale est une recherche côté public, elle est transformée en 404 avec set_404() et le code HTTP correspondant. is_admin() garde la recherche de l’administration intacte, is_main_query() évite de toucher aux requêtes secondaires des extensions.
  2. Le formulaire. get_search_form() est la fonction que les thèmes appellent pour afficher le formulaire, le filtre lui fait renvoyer une chaîne vide.
  3. Le widget des thèmes classiques.
  4. Le bloc des thèmes basés sur les blocs. Le filtre reçoit soit true (tous les blocs autorisés), soit une liste : dans le premier cas, on reconstruit la liste complète avant d’en retirer core/search.
  5. L’API REST. /wp-json/wp/v2/search?search=mot renvoie désormais une erreur rest_no_route au lieu d’une liste de résultats.

Vérifier

Trois requêtes suffisent, dans un navigateur ou avec curl :

bash
curl -s -o /dev/null -w "%{http_code}\n" "https://exemple.fr/?s=test"
# 404

curl -s "https://exemple.fr/wp-json/wp/v2/search?search=test" | head -c 120
# {"code":"rest_no_route","message":"Aucune route correspondante à l’URL et à la méthode de requête n’a été trouvée."…

curl -s "https://exemple.fr/" | grep -c 'role="search"'
# 0 : plus de formulaire dans la page (si le thème passe par get_search_form)

Dans l’administration, la recherche des articles, des pages et des médias doit continuer de fonctionner.

Si le thème affiche son propre formulaire

Certains thèmes écrivent le formulaire directement dans leurs gabarits (header.php, searchform.php) sans passer par get_search_form(). Le filtre n’a alors aucun effet sur l’affichage. Deux options : surcharger le gabarit concerné dans un thème enfant, ou masquer le formulaire en CSS en attendant :

css
.search-form,
form[role="search"] {
  display: none;
}

Le CSS ne fait que cacher : le blocage de /?s= par le premier bloc PHP reste indispensable.

Variante : rediriger ?s= en .htaccess

Si vous préférez ne pas servir une 404 mais renvoyer vers l’accueil, une règle Apache le fait avant même que WordPress ne s’exécute. Elle est limitée à la racine du site pour ne pas toucher la recherche de l’administration (wp-admin/edit.php?s=…).

.htaccess
# À placer avant le bloc # BEGIN WordPress
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)s= [NC]
RewriteRule ^$ /? [R=301,L]

Le ? final vide la chaîne de requête de la redirection. Cette règle et le code PHP ne s’excluent pas : la première épargne au serveur d’exécuter WordPress, le second reste la protection de référence, y compris pour les permaliens /search/mot/.

Il existe et fait la même chose. Sur Gekkode, la ligne éditoriale est de ne pas ajouter d’extension pour ce qu’un thème peut faire en trente lignes : une dépendance de moins à mettre à jour, et un comportement que vous lisez dans votre propre code. Si vous administrez plusieurs sites sans thème enfant, le plugin reste une option raisonnable.

Dans la même veine, limiter l’accès au back-office de WordPress et migrer un site WordPress sont deux autres opérations qui se font sans extension.

Erreurs fréquentes

Bloquer aussi la recherche de l’administration Un test is_search() sans is_admin() casse la recherche dans les listes d’articles et de médias du tableau de bord. Le code de l’article exclut l’administration.
Retirer le formulaire et oublier l’URL Le formulaire n’est qu’une porte : /?s=mot reste accessible à quiconque tape l’URL. C’est le filtre sur parse_query qui ferme la porte, pas la suppression du formulaire.
Une redirection .htaccess sur tout le site Une règle sur s= sans contrainte de chemin redirige aussi wp-admin/edit.php?s=…. Limitez la règle à la racine du site.
Un thème qui affiche son propre formulaire Si le thème n’utilise pas get_search_form(), le filtre ne le retire pas. Il faut alors modifier le gabarit du thème (enfant de préférence).

WordPress

Damien Flandrin Développeur web depuis 2010, créateur de Gekkode et d’Email Impact. Chaque article est testé sur un projet réel avant publication. Contact
Newsletter

Les nouveaux tests, tutoriels et projets, par e-mail.

Tests reproductibles, code versionné, résultats datés. Jamais de spam.