2026年11月12日

2026年11月12日

Hide WordPress Admin Menus by Role: remove_menu_page and Direct Access

This article is a localized edition of the Japanese original. Read the Japanese original

In the WordPress admin, the menus a user sees depend on the capabilities their role has. For example, "Plugins" requires activate_plugins and "Settings" requires manage_options, so Editors and Authors never see them, and if they open the URL directly, WordPress shows a message saying they are not allowed and the page does not open.

"Tools" and "Comments", on the other hand, only need edit_posts, so users with the Author role and above see them. This article shows how to clean up menus like these: pages a role is technically allowed to open but that you do not want to show. Everything here was checked against the WordPress 6.9 source code as of November 2026.

Main menu slugs and the capabilities they require

To remove a menu, you pass its "slug": the part of the admin URL after /wp-admin/.

Menu Slug Capability required to see it
Dashboard index.php read
Posts edit.php edit_posts
Media upload.php upload_files
Pages edit.php?post_type=page edit_pages
Comments edit-comments.php edit_posts
Appearance themes.php switch_themes or edit_theme_options
Plugins plugins.php activate_plugins
Users users.php list_users
Profile (for users who cannot see the user list) profile.php read
Tools tools.php edit_posts
Settings options-general.php manage_options

For a custom post type the menu slug is edit.php?post_type=投稿タイプ名 (use your post type name), and for a menu added by a plugin it is the xxx part of admin.php?page=xxx.

1. Hide menus

The code below hides "Tools" and "Comments" from everyone except administrators (users with the manage_options capability). Put it in your child theme's functions.php or in a PHP file inside wp-content/mu-plugins/.

<?php
add_action( 'admin_menu', function () {
    if ( current_user_can( 'manage_options' ) ) {
        return; // Administrators see everything
    }

    // Remove top-level menus
    remove_menu_page( 'tools.php' );          // Tools
    remove_menu_page( 'edit-comments.php' );  // Comments

    // Example: remove only a submenu (Posts -> Tags)
    remove_submenu_page( 'edit.php', 'edit-tags.php?taxonomy=post_tag' );
}, 999 );

The final 999 is the hook priority. A menu added by a plugin can only be removed after that plugin has registered it on admin_menu, so use a large number to run later.

The first argument of remove_submenu_page() is the parent menu slug and the second is the submenu slug.

2. Block direct access to the URL

remove_menu_page() only removes the item from the menu; it does not restrict access to the page. Anyone who knows the URL can still open /wp-admin/tools.php directly. To stop that, check the current page while the admin loads and halt.

<?php
add_action( 'admin_init', function () {
    if ( current_user_can( 'manage_options' ) || wp_doing_ajax() ) {
        return;
    }

    global $pagenow;

    $blocked_pages = array( 'tools.php', 'edit-comments.php' );

    if ( in_array( $pagenow, $blocked_pages, true ) ) {
        wp_die(
            esc_html( 'You do not have permission to view this page.' ),
            '',
            array( 'response' => 403, 'back_link' => true )
        );
    }
} );

$pagenow holds the file name of the admin screen being opened (such as tools.php). To block a plugin page (admin.php?page=xxx), check that 'admin.php' === $pagenow and that the value of $_GET['page'] is the slug you want to block.

The wp_doing_ajax() check is there so that plugins using admin-ajax.php keep working. If you would rather send users back to the Dashboard, use wp_safe_redirect( admin_url() ); exit; instead of wp_die().

3. Hide dashboard widgets

The default Dashboard widgets can be removed with remove_meta_box() on the wp_dashboard_setup hook.

<?php
add_action( 'wp_dashboard_setup', function () {
    if ( current_user_can( 'manage_options' ) ) {
        return;
    }
    remove_meta_box( 'dashboard_site_health', 'dashboard', 'normal' ); // Site Health Status
    remove_meta_box( 'dashboard_right_now',   'dashboard', 'normal' ); // At a Glance
    remove_meta_box( 'dashboard_activity',    'dashboard', 'normal' ); // Activity
    remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );   // Quick Draft
    remove_meta_box( 'dashboard_primary',     'dashboard', 'side' );   // WordPress Events and News
} );

The third argument is where the widget sits. By default "Quick Draft" and "WordPress Events and News" are in side, and the others are in normal.

Finding a menu’s slug

The easiest way is to hover over the menu in the admin and look at the link URL. The part after /wp-admin/ is the slug.

To list every menu added by plugins at once, enable WP_DEBUG and WP_DEBUG_LOG in wp-config.php, add the code below temporarily, and open the admin as an administrator. The slugs are written to wp-content/debug.log.

<?php
add_action( 'admin_menu', function () {
    global $menu, $submenu;
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    error_log( print_r( wp_list_pluck( $menu, 2 ), true ) );       // Top level
    error_log( print_r( array_map( function ( $items ) {
        return wp_list_pluck( $items, 2 );
    }, $submenu ), true ) );                                           // Submenus
}, PHP_INT_MAX );

The admin menu is only built when an admin screen is opened. If you try to print $menu with WP-CLI's wp eval, it is empty. Remove this code when you are done.

Removing the capability itself

If the goal is not just "don't show it" but "don't let them do it," remove the capability from the role instead of hiding the menu. For example, to take away an Editor's ability to approve and delete comments, run this with WP-CLI:

wp cap remove editor moderate_comments

Role capability changes are saved in the database and stay until you change them back. The same applies to add_cap() and remove_cap() in PHP, so do not put them in code that runs on every page load. These articles explain how capabilities work:

Things to watch out for

  • Even with a menu hidden, the same action may still be possible through the REST API or another screen. To stop the action itself, use the method in "Removing the capability itself" above.
  • If you get the administrator check wrong, the administrator's own menus disappear too. Before editing functions.php, make sure you can undo the change over FTP or with your host's file manager.
  • Code in functions.php stops working when you switch themes. To keep it regardless of theme, put it in wp-content/mu-plugins/.

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲