Disable Comments in WordPress Completely Without a Plugin

If a WordPress site has no blog, comments only attract spam. To disable comments in WordPress completely without a plugin, you have to switch them off in several places: post type support, the open/closed check, existing comments, block theme templates and the admin screens. This snippet covers all of them in one code block.

The snippet

<?php
/**
 * Disable comments everywhere: front end, block themes, REST, XML-RPC and wp-admin.
 */

// Remove comment and trackback support from every post type.
add_action( 'init', 'dpc_remove_comment_support', 100 );
function dpc_remove_comment_support(): void {
	foreach ( get_post_types() as $post_type ) {
		if ( post_type_supports( $post_type, 'comments' ) ) {
			remove_post_type_support( $post_type, 'comments' );
			remove_post_type_support( $post_type, 'trackbacks' );
		}
	}
}

// Close comments and pings. Forms, wp-comments-post.php, REST and pingbacks all check these.
add_filter( 'comments_open', '__return_false', 20 );
add_filter( 'pings_open', '__return_false', 20 );

// Hide existing comments and counts.
add_filter( 'comments_array', '__return_empty_array', 20 );
add_filter( 'get_comments_number', '__return_zero', 20 );

// Block themes query comments directly, so empty the comment blocks.
foreach ( array( 'core/comments', 'core/post-comments-form', 'core/post-comments-count', 'core/post-comments-link', 'core/latest-comments' ) as $dpc_block ) {
	add_filter( "render_block_{$dpc_block}", '__return_empty_string' );
}
unset( $dpc_block );

// No comments feed link, no Recent Comments widget.
add_filter( 'feed_links_show_comments_feed', '__return_false' );
add_action( 'widgets_init', 'dpc_unregister_comments_widget' );
function dpc_unregister_comments_widget(): void {
	unregister_widget( 'WP_Widget_Recent_Comments' );
}

// wp-admin: menu, screens and admin bar.
add_action( 'admin_menu', 'dpc_remove_comments_menu' );
function dpc_remove_comments_menu(): void {
	remove_menu_page( 'edit-comments.php' );
}

add_action( 'load-edit-comments.php', 'dpc_redirect_comments_screen' );
add_action( 'load-comment.php', 'dpc_redirect_comments_screen' );
function dpc_redirect_comments_screen(): void {
	wp_safe_redirect( admin_url() );
	exit;
}

add_action( 'admin_bar_menu', 'dpc_remove_comments_admin_bar', 999 );
function dpc_remove_comments_admin_bar( WP_Admin_Bar $admin_bar ): void {
	$admin_bar->remove_node( 'comments' );
}

How it works

  • Post types: on init at priority 100, after themes and plugins have registered their post types, comment and trackback support is removed, so the Discussion panel disappears from the editor.
  • Open or closed: comments_open and pings_open return false. WordPress checks these before it shows a form, before it accepts a comment through wp-comments-post.php or the REST API, and before it accepts a pingback.
  • Existing comments: comments_array is emptied for classic themes, and get_comments_number returns 0, so “3 Comments” links and counts disappear.
  • Block themes: the Comments, Comments Form, Comments Count, Comments Link and Latest Comments blocks render as empty strings, because block themes query comments directly instead of going through comments_array.
  • wp-admin: the Comments menu is removed, direct visits to edit-comments.php and comment.php redirect to the Dashboard, and the admin bar bubble, the Recent Comments widget and the comments feed link are gone.

Compared with the older One-Click Import version: support is removed on init instead of admin_init, so it also applies on the front end; the redirect uses load-{page} hooks and wp_safe_redirect(); block themes are covered; every function has the dpc_ prefix; and the removal of dashboard_recent_comments, a widget WordPress no longer has, is dropped.

Add it with Scripts Organizer

In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Everywhere, tick PHP under Script location, paste the code into the PHP editor and publish. Leave Action/Hook empty. Everywhere matters here: the code must run in wp-admin for the menus, on the front end for the templates, and in REST and wp-comments-post.php requests, which neither Admin only nor Conditions code reaches.

The same code also works unchanged in a small plugin or an mu-plugin.

Customise it

  • Keep WooCommerce reviews (they are comments of type review): in dpc_remove_comment_support() skip 'product', and replace the two __return_false filters with a function that returns false unless get_post_type( $post_id ) is 'product'.
  • Delete old comments for good: empty them in Comments before you enable the snippet, or run wp comment delete $(wp comment list --format=ids) --force with WP-CLI.

Gotchas

  • Comments are hidden, not deleted. Disable the code block and they come back.
  • The Activity box on the Dashboard can still list comments that already exist.
  • WooCommerce product reviews are comments too, so they are closed and hidden unless you apply the customisation above.
  • Don’t expect a measurable speed gain; the benefit is no spam and a cleaner admin.

In the Scripts Organizer library Import it with one click from Scripts Organizer.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You’ll also get DPlugins product updates. No spam, and you can unsubscribe anytime.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You'll also get DPlugins product updates. No spam, and you can unsubscribe anytime.