In this full complete guide, I will show you how to hide Woocommerce shipping methods conditionally without any extra plugin. Before you jump in a quick comment though: all the snippets shown below will go to either to your child theme’s functions.php file or, better yet, use Code Snippets plugin for it.
Video: How to Conditionally Hide Woocommerce Shipping Methods
If you’re not good at adding code snippets on your site, then take a look at this video.
How to disable Woocommerce shipping methods for a specific shipping class?
Now, there are two things you would need to do beforehand:
- Add a shipping class. Go to Woocommerce >> Settings >> Shipping >> Shipping classes and add one. For example: “Courier only”
- Write down the shipping class slug because you will need it later. Where to get the slug? See the screenshot below.
- Add shipping class to the needed product. Open your product and see under Shipping tab.

Next, go to Snippets >> Add new and paste this snippet here below inside your code box. Pay attention though that you need to change the shipping class slug on line 4 accordingly.
So, if in this example I have a “Courier only” shipping class with a slug “courier-only”, then replace the slug in the code accordingly with the correct one.
One more thing, on line 12 there is a shipping method that you are hiding (Flat rate). Change the shipping method name and ID as needed. How to find your shipping ID number? Well, take a look at the video above (see the 3min 44sec mark).
/* Hide WooCommerce shipping method for a specific shipping class */
function hide_flat_rate_shipping( $rates, $package ) {
// Shipping class IDs that need the method removed
$shipping_classes = array('pakk1'); // Here goes your shipping class slug
$if_exists = false;
foreach( $package['contents'] as $key => $values ) {
if( in_array( $values['data']->get_shipping_class(), $shipping_classes ) )
$if_exists = true;
}
if( $if_exists ) {
unset( $rates['montonio_venipak_courier:4'] ); // Here goes your shipping method that needs to be hidden. Don’t forget to add the correct one here
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_flat_rate_shipping', 10, 2 );
If you would like to know how to hide Woocommerce multiple shipping methods using shipping classes, then see my previous post here.
How to Hide Woocommerce Checkout Fields When Local Pickup is Selected?
One of the most annoying things with the Woocommerce shiping system is that if Local Pickup shipping method is chosen then you still need to fill in all the address and postcode fields. But what if you could automatically hide those fields if Local pickup method is chosen?
/* This piece of code will hide fields for the chosen method.
.hide_pickup {
display: none !important;
}
*/
// Hide Local Pickup shipping method
add_filter( 'woocommerce_checkout_fields', 'hide_local_pickup_method' );
function hide_local_pickup_method( $fields_pickup ) {
// change below for the method
$shipping_method_pickup ='local_pickup:2';
// change below for the list of fields. Add (or delete) the field name you want (or don’t want) to use
$hide_fields_pickup = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city', 'billing_state');
$chosen_methods_pickup = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping_pickup = $chosen_methods_pickup[0];
foreach($hide_fields_pickup as $field_pickup ) {
if ($chosen_shipping_pickup == $shipping_method_pickup) {
$fields_pickup['billing'][$field_pickup]['required'] = false;
$fields_pickup['billing'][$field_pickup]['class'][] = 'hide_pickup';
}
$fields_pickup['billing'][$field_pickup]['class'][] = 'billing-dynamic_pickup';
}
return $fields_pickup;
}
// Local Pickup - hide fields
add_action( 'wp_head', 'local_pickup_fields', 999 );
function local_pickup_fields() {
if (is_checkout()) :
?>
<style>
.hide_pickup {display: none!important;}
</style>
<script>
jQuery( function( $ ) {
if ( typeof woocommerce_params === 'undefined' ) {
return false;
}
$(document).on( 'change', '#shipping_method input[type="radio"]', function() {
// change local_pickup:4 accordingly
$('.billing-dynamic_pickup').toggleClass('hide_pickup', this.value == 'local_pickup:2');
});
});
</script>
<?php
endif;
}
Now, pay attention that the snippet above works only with one Local Pickup Shipping method. If you have multiple Local Pickup selections, then the code above works only with one of them and then you should use this snippet here below
How to Hide Woocommerce Checkout Fields Based on Shipping Methods?
This one here is a bit tricky one and will do this:
- If Local pickup (local_pickup:2) is selected, Billing country, postcode, address 1, address 2 and city fields are disabled.
- If Local Pickup 2 (local_pickup:8) is selected, Billing country, postcode, address 1, address 2 and city fields are disabled.
- If Local pickup (multiparcels_smartpost_pickup_point:7) is selected, Billing country, postcode, address 1, address 2 and city and phone fields are disabled.
If you would like to use this snippet, then take a look at line 30 for changing your shipping ID. Line 33 contains fields to be hidden. And line 70 should once again contains your shipping method. So, everything between lines 25 and 76 contains code for Local pickup method. Lines 78-130 is used for Local pickup 2 and lines 132-182 are for SmartPost shipping method.
In a similar way you can add (or remove) your own additional shipping methods.
/* CSS classes for hiding fields
.hide_local {
display: none !important;
}
.hide_local2 {
display: none !important;
}
.hide_smartpost {
display: none !important;
}
AVAILABLE BILLING FIELDS
billing_company = COMPANY
billing_country = COUNTRY
billing_postcode = POSTCODE
billing_address_1 = ADDRESS 1
billing_address_2 = ADDRESS 2
billing_city = CITY
billing_last_name = LAST NAME
billing_first_name = FIRST NAME
billing_phone = PHONE
billing_state = STATE
*/
// Hide local pickup fields
add_filter( 'woocommerce_checkout_fields', 'wpsh_hide_local_pickup_fields' );
function wpsh_hide_local_pickup_fields( $fields_itella ) {
// Add your own shipping method ID
$shipping_method_itella ='local_pickup:2';
// change below for the list of fields
$hide_fields_itella = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city' );
$chosen_methods_itella = WC()->session->get( 'chosen_shipping_methods' );
// uncomment below line and reload checkout page to check current $chosen_methods
// print_r($chosen_methods);
$chosen_shipping_itella = $chosen_methods_itella[0];
foreach($hide_fields_itella as $field_itella ) {
if ($chosen_shipping_itella == $shipping_method_itella) {
$fields_itella['billing'][$field_itella]['required'] = false;
$fields_itella['billing'][$field_itella]['class'][] = 'hide_local';
}
$fields_itella['billing'][$field_itella]['class'][] = 'billing-dynamic_itella';
}
return $fields_itella;
}
// Local pickup Ajax
add_action( 'wp_head', 'wpsh_local_pickup_ajax', 999 );
function wpsh_local_pickup_ajax() {
if (is_checkout()) :
?>
<style>
.hide_local {display: none!important;}
</style>
<script>
jQuery( function( $ ) {
// woocommerce_params is required to continue, ensure the object exists
if ( typeof woocommerce_params === 'undefined' ) {
return false;
}
$(document).on( 'change', '#shipping_method input[type="radio"]', function() {
// Add your own shipping method ID
$('.billing-dynamic_itella').toggleClass('hide_local', this.value == 'local_pickup:2');
});
});
</script>
<?php
endif;
}
// // Hide local pickup 2 fields
add_filter( 'woocommerce_checkout_fields', 'wpsh_hide_local_pickup2_fields' );
function wpsh_hide_local_pickup2_fields( $fields_omniva ) {
// Add your own shipping method ID
$shipping_method_omniva ='local_pickup:8';
// change below for the list of fields
$hide_fields_omniva = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city' );
$chosen_methods_omniva = WC()->session->get( 'chosen_shipping_methods' );
// uncomment below line and reload checkout page to check current $chosen_methods
// print_r($chosen_methods);
$chosen_shipping_omniva = $chosen_methods_omniva[0];
foreach($hide_fields_omniva as $field_omniva ) {
if ($chosen_shipping_omniva == $shipping_method_omniva) {
$fields_omniva['billing'][$field_omniva]['required'] = false;
$fields_omniva['billing'][$field_omniva]['class'][] = 'hide_local';
}
$fields_omniva['billing'][$field_omniva]['class'][] = 'billing-dynamic_omniva';
}
return $fields_omniva;
}
// Local pickup 2 Ajax
add_action( 'wp_head', 'wpsh_hide_local_pickup2_ajax', 999 );
function wpsh_hide_local_pickup2_ajax() {
if (is_checkout()) :
?>
<style>
.hide_local2 {display: none!important;}
</style>
<script>
jQuery( function( $ ) {
// woocommerce_params is required to continue, ensure the object exists
if ( typeof woocommerce_params === 'undefined' ) {
return false;
}
$(document).on( 'change', '#shipping_method input[type="radio"]', function() {
// Add your own shipping method ID
$('.billing-dynamic_omniva').toggleClass('hide_local2', this.value == 'local_pickup:8');
});
});
</script>
<?php
endif;
}
// Hide SmartPost fields
add_filter( 'woocommerce_checkout_fields', 'wpsh_hide_smartpost_fields' );
function wpsh_hide_smartpost_fields( $fields_pickup ) {
// Add your own shipping method ID
$shipping_method_pickup ='multiparcels_smartpost_pickup_point:7';
// change below for the list of fields
$hide_fields_pickup = array( 'billing_company', 'billing_country', 'billing_postcode', 'billing_address_1', 'billing_address_2' , 'billing_city', 'billing_phone' );
$chosen_methods_pickup = WC()->session->get( 'chosen_shipping_methods' );
// uncomment below line and reload checkout page to check current $chosen_methods
// print_r($chosen_methods);
$chosen_shipping_pickup = $chosen_methods_pickup[0];
foreach($hide_fields_pickup as $field_pickup ) {
if ($chosen_shipping_pickup == $shipping_method_pickup) {
$fields_pickup['billing'][$field_pickup]['required'] = false;
$fields_pickup['billing'][$field_pickup]['class'][] = 'hide_smartpost';
}
$fields_pickup['billing'][$field_pickup]['class'][] = 'billing-dynamic_pickup';
}
return $fields_pickup;
}
// Samrtpost Ajax
add_action( 'wp_head', 'wpsh_hide_smartpost_fields_ajax', 999 );
function wpsh_hide_smartpost_fields_ajax() {
if (is_checkout()) :
?>
<style>
.hide_smartpost {display: none!important;}
</style>
<script>
jQuery( function( $ ) {
// woocommerce_params is required to continue, ensure the object exists
if ( typeof woocommerce_params === 'undefined' ) {
return false;
}
$(document).on( 'change', '#shipping_method input[type="radio"]', function() {
// Add your own shipping method ID
$('.billing-dynamic_pickup').toggleClass('hide_smartpost', this.value == 'multiparcels_smartpost_pickup_point:7');
});
});
</script>
<?php
endif;
}
How to display Woocommerce store address for Local pickup shipping method?
The first thing you need to do is you need to find out your Local pickup ID number.
If you don’t know how to do that then go to Woocommerce >> Settings >> Shipping >> Open your shipping zone.
Now hover on the Local pickup method and see the link. It is something like this:
https://yoursite.com/wp-admin/admin.php?page=wc-settings&tab=shipping&instance_id=2
See the ID=2, this is your shipping method ID.
Now add this piece of CSS inside Appearace >> Customizer >> Additional CSS code box.
#shipping_method_0_local_pickup2:checked + label[for=shipping_method_0_local_pickup2]::after {
display: block;
content: "London, Buckingham palace";
color: red;
font-weight: 600;
}
How to disable Woocommerce shipping methods based on specific category?
With the help of this code here below, you can disable Woocommerce shipping methods based on specific category. Take a look at the comments and change your categories and shipping methods accordingly.
For example: this code hides Flat, rate, Local pickup and DPD Pickup point shipping methods if the cart contains product from the Lightning category.
// Disable Woocommerce shipping methods based on specific category
add_filter( 'woocommerce_package_rates', 'hide_shipping_for_categories', 10, 2 );
function hide_shipping_for_categories( $rates, $package ) {
// Add your own Woocommerce categories here (either category ID, slug or name)
$terms = array( 'lightning' );
$taxonomy = 'product_cat'; // If you need to hide shipping based on tags, then change it to product_tag
// Add shipping methods to be removed (like "local_pickup:8")
$method_instances_ids = array('flat_rate:1','local_pickup:8', 'multiparcels_dpd_pickup_point:13');
$found = false;
// Loop through cart items checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
if ( has_term( $terms, $taxonomy, $cart_item['product_id'] ) ){
$found = true;
break;
}
}
if ( ! $found ) return $rates; // If not found we exit
// Loop through your active shipping methods
foreach( $rates as $rate_id => $rate ) {
// Remove all other shipping methods other than your defined shipping method
if ( in_array( $rate_id, $method_instances_ids ) ){
unset( $rates[$rate_id] );
}
}
return $rates;
}
How to disable Woocommerce shipping methods based on specific product tag?
If you need to disable Woocommerce shipping methods based on specific product tag then just use the code above (the one I used for product categories) and replace $taxonomy = ‘product_cat’; on line 5 with $taxonomy = ‘product_tag’;
Now change the tag slug, ID or name in line 5 and you’re good to go.
How to disable Woocommerce shipping methods based on specific products in your cart?
Now let’s take a look at how to disable Woocommerce shipping methods based on specific products in your cart. Once again, add your own product ID-s in line 5 and change shipping methods in line 7.
// Disable Woocommerce shipping methods based on specific products in your cart
add_filter( 'woocommerce_package_rates', 'wpsh_hide_shipping_for_specific_products', 10, 2 );
function wpsh_hide_shipping_for_specific_products( $rates, $package ) {
// Add product IDs here below
$product_ids = array( 426, 115, 126 );
// Add shipping methods you need to be removed (for example: local_pickup:8)
$method_instances_ids = array('flat_rate:1', 'local_pickup:2');
$found = false;
// Loop through cart items checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
if ( in_array( $cart_item['product_id'], $product_ids ) ){
$found = true;
break;
}
}
if ( ! $found ) return $rates; // If not found we exit
// Loop through your active shipping methods
foreach( $rates as $rate_id => $rate ) {
// Remove all other shipping methods other than your defined shipping method
if ( in_array( $rate_id, $method_instances_ids ) ){
unset( $rates[$rate_id] );
}
}
return $rates;
}
How to disable Woocommerce shipping methods based on specific products vartiations / attributes in your cart?
What if you need to disable Woocommerce shipping methods based on specific products variations or attributes added to the cart? No worries, I’ve got you covered.
Take a look at the lines 8 and 9. As you see they contain $taxonomy = ‘pa_color’; and $taxonomy = ‘pa_condition’; Those are for the attributes on my site (color and condition). Just replace these with your own attribute slugs (pa_size for example).
How can you find your attribute slug? Go to Products >> Attributes and there it is. See the screenshot.

Next, take a look at lines 13-15. There you can set up which Woocommerce shipping methods are disabled for the specific terms. Just replace the rems slug accordingly.
// Disable Woocommerce shipping methods based on specific products vartiations / attributes in your cart
add_filter( 'woocommerce_package_rates', 'wpsh_hide_shipping_for_atttributes', 10, 2 );
function wpsh_hide_shipping_for_atttributes( $rates, $package ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ATTENTION: You need to define the product attibute taxonomy (starts always with "pa_")
$taxonomy = 'pa_color'; // Example for "Color"
$taxonomy = 'pa_condition'; // Example for "Condition"
// HERE define shipping method rate ID to be removed from product attribute term(s) slug(s) (pairs) in this array
$data_array = array(
'local_pickup:2' => array('black','white', 'used'),
'multiparcels_dpd_pickup_point:13' => array('black', 'white', 'used'),
'flat_rate:1' => array('black','white'),
);
// Loop through cart items
foreach( $package['contents'] as $cart_item ){
if( isset($cart_item['variation']['attribute_'.$taxonomy]) ) {
// The product attribute selected term slug
$term_slug = $cart_item['variation']['attribute_'.$taxonomy];
// Loop through our data array
foreach( $data_array as $rate_id => $term_slugs ) {
if( in_array($term_slug, $term_slugs) && isset($rates[$rate_id]) ) {
// We remove the shipping method corresponding to product attribute term as defined
unset($rates[$rate_id]);
}
}
}
}
return $rates;
}
How to disable Woocommerce shipping methods based on cart subtotal?
Sometimes it is useful to disable Woocommerce shipping methods based on cart subtotal. If this is the case then use this snippet.
Pay attention to the lines 7-8 for shipping methods. Also, pay attention, that flat rate is set up as $shipping_id = ‘flat_rate:1’; and local pickup as $shipping_id1 = ‘flat_rate:1’; Did you notice 1 added to the ID?
Now, take a look at the lines 10-13. As you see, if the subtotal is mor than 300USD then Local pickup (that is $shipping_id1) is disabled. If subtotal is more than 140USD then Flat rate (that is $shipping_id) is disabled.
So, change and add these values accordingly.
// Disable Woocommerce shipping methods based on cart subtot
add_filter( 'woocommerce_package_rates', 'wpsh_hide_shipping_based_on_subtotal', 10, 2 );
function wpsh_hide_shipping_based_on_subtotal( $rates, $package ) {
// Retrieve cart subtotal
$cart_subtotal = $package['contents_cost'];
// Shipping rate to be excluded
$shipping_id = 'flat_rate:1';
$shipping_id1 = 'local_pickup:2';
if ( $cart_subtotal >= 300 )
unset( $rates[ $shipping_id1 ] );
elseif( $cart_subtotal >= 140 )
unset( $rates[ $shipping_id ] );
return $rates;
}
How to disable Woocommerce shipping methods based on cart weight?
This is useful if some shipping providers are not accepting packages that weigh more than 50 kilograms or something like that. So, if you need to disable Woocommerce shipping methods based on cart weight, then use this snippet. Take a look at the line 5 and change the weight as needed .
With this example, I disable flat rate and local pickup methods if the cart weight is more than 50 kilograms.
// Disable Woocommerce shipping methods based on cart weight
add_filter( 'woocommerce_package_rates', 'wpsh_hide_based_on_weight', 9999, 2 );
function wpsh_hide_based_on_weight( $rates, $package ) {
if ( WC()->cart->get_cart_contents_weight() > 50 ) {
unset( $rates['flat_rate:1'], $rates['local_pickup:2'] );
}
return $rates;
}
As a side note: if you would like to display order total weight on Woocommerce cart and checkout pages, then use this snippet here below.
// Display order total weight on Woocommerce cart page
add_action( 'woocommerce_before_cart', 'wpsh_display_total_weight' );
add_action( 'woocommerce_before_checkout_form', 'wpsh_display_total_weight' );
function wpsh_display_total_weight() {
$notice = 'Your cart weight is: ' . WC()->cart->get_cart_contents_weight() . get_option( 'woocommerce_weight_unit' );
if ( is_cart() ) {
wc_print_notice( $notice, 'notice' );
} else {
wc_add_notice( $notice, 'notice' );
}
}
How to hide all shipping rates when free shipping is available?
So, you offer free shipping on your site, and you would like to hide all shipping rates when free shipping is available? Use this small snippet to accomplish that.
// Hide all shipping rates when free shipping is available
function wpsh_hide_if_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'wpsh_hide_if_when_free_is_available', 100 );
How to hide all shipping rates when free shipping is available, but keep “Local pickup?
Let’s tweak this solution I showed in previous chapten and hide all shipping rates when free shipping is available, but keep “Local pickup” method.
// Hide all shipping rates when free shipping is available, but keep "Local pickup" method
add_filter( 'woocommerce_package_rates', 'wpsh_hide_if_free', 100 );
function wpsh_hide_if_free($rates) {
$free = $local = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
} elseif ( 'local_pickup' === $rate->method_id ) {
$local[ $rate_id ] = $rate;
}
}
return ! empty( $free ) ? array_merge( $free, $local ) : $rates;
}
How to hide WooCommerce Shipping Methods Based on User Roles?
Well, this one here is a nice one and allows you to hide Woocommerce shipping methods based on user roles. At the moment this code does this:
- Hides Local pickup and Flat rate methods for Adminsitrators (see line 6)
- Hides Free shipping and Flat rate for Customers (see line 7)
- Hides Smartpost and DPD methods for all other user roles (see lines 25 and 26)
Just tweak these lines accordingly and you’re good to go.
// Hide WooCommerce Shipping Methods Based on User Roles
add_filter( 'woocommerce_package_rates', function( $shipping_rates ) {
if(is_user_logged_in()) {
// Provide user role and shipping method ID you want to hide for the user role.
$role_shipping_method_arr = array(
'administrator' => array( 'local_pickup:2','flat_rate:1'),
'customer' => array( 'free_shipping:6','flat_rate:5'),
);
$current_user = wp_get_current_user();
foreach( $role_shipping_method_arr as $role => $shipping_methods_to_hide ) {
// Check if defined role exist in current user role or not
if(in_array( $role, $current_user->roles) ) {
// Loop through all the shipping rates
foreach( $shipping_rates as $shipping_method_key => $shipping_method ) {
$shipping_id = $shipping_method->get_id();
// Unset the shipping method if found
if( in_array( $shipping_id, $shipping_methods_to_hide) ) {
unset($shipping_rates[$shipping_method_key]);
}
}
}
}
} else {
unset($shipping_rates['multiparcels_smartpost_pickup_point:7']);
unset($shipping_rates['multiparcels_dpd_pickup_point:13']);
}
return $shipping_rates;
} );
How to remove “Ship to adifferent address” if Local Pickup is selected?
There is no need for “ship to a different address” section if customer has chosen Local pickup as a shiping method. Therefore, let’s “ship to different address” if Local Pickup is selected.
// Remove "ship to a different address" if Local Pickup is selected
add_action( 'woocommerce_after_checkout_form', 'wpsh_remove_ship_to_section' );
function wpsh_remove_ship_to_section( $available_gateways ) {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( 0 === strpos( $chosen_shipping, 'local_pickup' ) ) {
?>
<script type="text/javascript">
jQuery('#customer_details .col-2 .woocommerce-shipping-fields').fadeOut();
</script>
<?php
}
?>
<script type="text/javascript">
jQuery('form.checkout').on('change','input[name^="shipping_method"]',function() {
var val = jQuery( this ).val();
if (val.match("^local_pickup")) {
jQuery('#customer_details .col-2 .woocommerce-shipping-fields').fadeOut();
} else {
jQuery('#customer_details .col-2 .woocommerce-shipping-fields').fadeIn();
}
});
</script>
<?php
}
How to Remove “Ship to a different address” only for specific products in Woocommerce
Take a look at line 5 which contains product ID-s. So, at the moment, “Ship to a different address” selection is activated only for products with ID-s 2545 and 400. If the cart contains a product with other ID-s, then “ship to a different address” is deactivated.
// Remove "Ship to a different address" only for specific products in Woocommerce
add_filter( 'woocommerce_cart_needs_shipping_address', 'wpsh_disable_checkout_shipping_address');
function wpsh_disable_checkout_shipping_address( $needs_shipping_address ) {
$products_ids = array(2545, 400);
$found = $others_found = false;
foreach ( WC()->cart->get_cart() as $cart_item ){
if (in_array( $cart_item['data']->get_id(), $products_ids ) ){
$found = true;
} else {
$others_found = true;
}
}
if( $found && ! $others_found )
$needs_shipping_address = true;
else
$needs_shipping_address = false;
return $needs_shipping_address;
}