I want to display Current product shipping rate on the product detail page.

I have tried below code,

$qty = 1;
        $storeId = 1;
        $zipcode = 360002;
        $product = $this->_catalogProduct->load($id);
        $item = $objectManager->create('Magento\Quote\Model\Quote\Item')->setProduct($product)->setQty(1);
        $store = $objectManager->create('Magento\Store\Model\Store')->load($storeId);
        $request = $objectManager->create('Magento\Quote\Model\Quote\Address\RateRequest')->setAllItems(array($item))
         $result = $this->_rateCollector->create()->collectRates($request)->getResult();

I want to display more than one enabled shipping methods rates in product display page. I have tried this code but i am getting this kind of error.

Uncaught Error: Call to a member function getItemsQty() on null in/vendor/magento/module-quote/Model/Quote/Item.php:275

Please help me on this.


Although Manish's answer does show how to create a block on the product page to obtain the available shipping rates, the REST API used in the tutorial (rest/default/V1/carts/mine/estimate-shipping-methods) only fetches this for the items that are already in the cart, and not just for the currently viewed product. This is because Magento relies on items that are added to the active quote to obtain the available methods and costs, of which was fetched from the database and utilised. Despite this, we can create a blank quote in memory without saving it into the database, fill in the required data, and then apply this to the shipping calculator.

The best approach to this is to create a new API endpoint, which you can then swap out the endpoint defined in the tutorial with yours.



namespace Your\Module\Api;

use Magento\Quote\Api\Data\AddressInterface;

 * Interface ShipmentForProductEstimationInterface
 * @api
 * @since 100.0.7
interface ShipmentForProductEstimationInterface
     * Estimate shipping by address and product, and return list of available shipping methods
     * @param string $sku
     * @param AddressInterface $address
     * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods
    public function estimateByProductAndAddress($sku, AddressInterface $address);



namespace Your\Module\Model\Api;

use Magento\Framework\App\ObjectManager;

class ShipmentForProductEstimation implements \Your\Module\Api\ShipmentForProductEstimationInterface {

     * Shipping method converter
     * @var \Magento\Quote\Model\Cart\ShippingMethodConverter
    protected $converter;

     * @var \Magento\Quote\Model\Quote\TotalsCollector
    protected $totalsCollector;

     * @var \Magento\Framework\Reflection\DataObjectProcessor
    protected $dataProcessor;

     * @var \Magento\Quote\Model\Quote
    protected $quote;

     * @var \Magento\Catalog\Api\ProductRepositoryInterface
    protected $product;

     * @var \Magento\Quote\Model\Quote\Item
    protected $item;

    public function __construct(
        \Magento\Quote\Model\Cart\ShippingMethodConverter $converter,
        \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector,
        \Magento\Quote\Model\Quote $quote,
        \Magento\Catalog\Api\ProductRepositoryInterface $product,
        \Magento\Quote\Model\Quote\Item $item
    ) {
        $this->converter = $converter;
        $this->totalsCollector = $totalsCollector;
        $this->quote = $quote;
        $this->product = $product;
        $this->item = $item;

     * @inheritdoc
    public function estimateByProductAndAddress($sku, \Magento\Quote\Api\Data\AddressInterface $address)
        $output = [];


        $p = $this->product->get($sku);


        $this->quote->addItem( $this->item );

        $shippingAddress = $this->quote->getShippingAddress();

        $this->totalsCollector->collectAddressTotals($this->quote, $shippingAddress);
        $shippingRates = $shippingAddress->getGroupedAllShippingRates();
        foreach ($shippingRates as $carrierRates) {
            foreach ($carrierRates as $rate) {
                $output[] = $this->converter->modelToDataObject($rate, $this->quote->getQuoteCurrencyCode());
        return $output;


     * Get transform address interface into Array
     * @param \Magento\Framework\Api\ExtensibleDataInterface  $address
     * @return array
    protected function extractAddressData($address)
        $className = \Magento\Customer\Api\Data\AddressInterface::class;
        if ($address instanceof \Magento\Quote\Api\Data\AddressInterface) {
            $className = \Magento\Quote\Api\Data\AddressInterface::class;
        } elseif ($address instanceof \Magento\Quote\Api\Data\EstimateAddressInterface) {
            $className = \Magento\Quote\Api\Data\EstimateAddressInterface::class;
        return $this->getDataObjectProcessor()->buildOutputDataArray(

     * Gets the data object processor
     * @return \Magento\Framework\Reflection\DataObjectProcessor
    protected function getDataObjectProcessor()
        if ($this->dataProcessor === null) {
            $this->dataProcessor = ObjectManager::getInstance()->get(\Magento\Framework\Reflection\DataObjectProcessor::class);
        return $this->dataProcessor;



<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Your\Module\Api\ShipmentForProductEstimationInterface" type="Your\Module\Model\Api\ShipmentForProductEstimation" />


<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route url="/V1/shipping/estimate/:sku" method="POST">
        <service class="Your\Module\Api\ShipmentForProductEstimationInterface" method="estimateByProductAndAddress"/>
            <resource ref="anonymous" />

If you are familiar with API endpoints, you will recognise that this can be called via /rest/default/V1/shipping/estimate/:sku, where :sku is the product SKU you would like to check the shipping methods for. The POST object and return JSON will be exactly the same as that of carts/mine/estimate-shipping-methods, so they are interchangeable.

If the rates displayed are different from when you add the item into the active cart, then that suggests the shipping rate fetches the item and/or address data from the session rather than the Magento\Quote\Model\Quote\Address\RateRequest object - if this is the case, then you may need to alter those shipping classes, or contact the developer to have this looked into.

  • This helped me a lot. to debug and i understand. – Padhiyar Gaurang Jul 1 '20 at 9:18
  • if i call /rest/default/V1/shipping/estimate/:sku i got this <response> <message>Specified request cannot be processed.</message> <trace/> </response> – krybbio Jul 8 '20 at 14:50
  • removing default from url works /rest//V1/shipping/estimate/:sku. Magento 2.3.5 – krybbio Jul 8 '20 at 16:11

Refer below link for displaying Shipping Rate on Product Details Page



The Smithee aproach works, but what about configurable products if one of them has differents size? In frontend doesnt show SKU, how to get SKU from a simpleproduct linked with a configurableproduct?

  • So your question is: How do I get the SKU of a child product by knowing the SKU of the configurable parent product? – Mohammed Joraid Sep 28 '20 at 11:13
  • 1
    Yes I forgot I'd asked it but I was able to have it working... I did it a JavaScript got a JSON from $('#product_addtocart_form') and get super_attribute value, so send it to my PHP class, whose I verify the product type and if its a configurable, I use the method getProductByAttributes from \Magento\ConfigurableProduct\Model\Product\Type\Configurable, once it returns a product I just add it to quote. If someone need I can explain it better or post the code, but its easy to understand I guess... – jefferson Oct 5 '20 at 18:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.