diff --git a/cmd/neofs-lens/internal/commands/inspect/inspect.go b/cmd/neofs-lens/internal/commands/inspect/inspect.go
new file mode 100644
index 000000000..802165eda
--- /dev/null
+++ b/cmd/neofs-lens/internal/commands/inspect/inspect.go
@@ -0,0 +1,116 @@
+package inspect
+
+import (
+	"fmt"
+	"io/ioutil"
+
+	"github.com/nspcc-dev/neofs-api-go/pkg/object"
+	common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
+	"github.com/spf13/cobra"
+)
+
+const (
+	flagAddress    = "address"
+	flagEnginePath = "path"
+	flagHeader     = "header"
+	flagOutFile    = "out"
+	flagWriteCache = "writecache"
+)
+
+var (
+	vAddress    string
+	vHeader     bool
+	vPath       string
+	vOut        string
+	vWriteCache bool
+)
+
+// Command contains `inspect` command definition.
+var Command = &cobra.Command{
+	Use:   "inspect",
+	Short: "Object inspection",
+	Long:  `Inspect specific object in storage engine component.`,
+	Run:   objectInspectCmd,
+}
+
+func init() {
+	Command.Flags().StringVar(&vAddress, flagAddress, "", "Object address")
+	_ = Command.MarkFlagRequired(flagAddress)
+
+	Command.Flags().StringVar(&vPath, flagEnginePath, "",
+		"Path to storage engine component",
+	)
+	_ = Command.MarkFlagFilename(flagEnginePath)
+	_ = Command.MarkFlagRequired(flagEnginePath)
+
+	Command.Flags().StringVar(&vOut, flagOutFile, "",
+		"File to save object payload")
+
+	Command.Flags().BoolVar(&vHeader, flagHeader, false, "Inspect only header")
+	Command.Flags().BoolVar(&vWriteCache, flagWriteCache, false,
+		"Process write-cache")
+}
+
+func objectInspectCmd(cmd *cobra.Command, _ []string) {
+	addr := object.NewAddress()
+	err := addr.Parse(vAddress)
+	common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err))
+
+	if vOut == "" && !vHeader {
+		common.ExitOnErr(cmd, fmt.Errorf("either --%s or --%s flag must be provided",
+			flagHeader, flagOutFile))
+	}
+
+	if vWriteCache {
+		db, err := writecache.OpenDB(vPath, true)
+		common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err))
+
+		defer db.Close()
+
+		data, err := writecache.Get(db, []byte(addr.String()))
+		common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err))
+		printObjectInfo(cmd, data)
+		return
+	}
+
+	blz := blobovnicza.New(
+		blobovnicza.WithPath(vPath),
+		blobovnicza.ReadOnly())
+	common.ExitOnErr(cmd, blz.Open())
+
+	defer blz.Close()
+
+	prm := new(blobovnicza.GetPrm)
+	prm.SetAddress(addr)
+	res, err := blz.Get(prm)
+	common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err))
+
+	printObjectInfo(cmd, res.Object())
+}
+
+func printObjectInfo(cmd *cobra.Command, data []byte) {
+	obj := object.New()
+	err := obj.Unmarshal(data)
+	common.ExitOnErr(cmd, common.Errf("can't unmarshal object: %w", err))
+
+	if vHeader {
+		cmd.Println("Version:", obj.Version())
+		cmd.Println("Type:", obj.Type())
+		cmd.Println("CID:", obj.ContainerID())
+		cmd.Println("ID:", obj.ID())
+		cmd.Println("Owner:", obj.OwnerID())
+		cmd.Println("CreatedAt:", obj.CreationEpoch())
+		cmd.Println("PayloadSize:", obj.PayloadSize())
+		cmd.Println("Attributes:")
+		for _, attr := range obj.Attributes() {
+			cmd.Printf("  %s: %s\n", attr.Key(), attr.Value())
+		}
+	}
+
+	if vOut != "" {
+		err := ioutil.WriteFile(vOut, obj.Payload(), 0644)
+		common.ExitOnErr(cmd, common.Errf("couldn't write payload: %w", err))
+	}
+}
diff --git a/cmd/neofs-lens/root.go b/cmd/neofs-lens/root.go
index ba1f6bd7d..f27ae7744 100644
--- a/cmd/neofs-lens/root.go
+++ b/cmd/neofs-lens/root.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"os"
 
+	"github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/commands/inspect"
 	cmdlist "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/commands/list"
 	"github.com/nspcc-dev/neofs-node/misc"
 	"github.com/spf13/cobra"
@@ -34,6 +35,7 @@ func entryPoint(cmd *cobra.Command, _ []string) error {
 func init() {
 	command.AddCommand(
 		cmdlist.Command,
+		inspect.Command,
 	)
 }
 
diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go
index 5c3593b41..d93eee45e 100644
--- a/pkg/local_object_storage/writecache/get.go
+++ b/pkg/local_object_storage/writecache/get.go
@@ -20,17 +20,8 @@ func (c *cache) Get(addr *objectSDK.Address) (*object.Object, error) {
 	}
 	c.mtx.RUnlock()
 
-	var value []byte
-	_ = c.db.View(func(tx *bbolt.Tx) error {
-		b := tx.Bucket(defaultBucket)
-		val := b.Get([]byte(saddr))
-		if val != nil {
-			value = cloneBytes(val)
-		}
-		return nil
-	})
-
-	if value != nil {
+	value, err := Get(c.db, []byte(saddr))
+	if err == nil {
 		obj := object.New()
 		c.flushed.Get(saddr)
 		return obj, obj.Unmarshal(value)
@@ -66,3 +57,22 @@ func (c *cache) Head(addr *objectSDK.Address) (*object.Object, error) {
 	// NOTE: resetting the payload via the setter can lead to data corruption of in-memory objects, but ok for others
 	return object.NewRawFromObject(obj).CutPayload().Object(), nil
 }
+
+// Get fetches object from the underlying database.
+// Key should be a stringified address.
+func Get(db *bbolt.DB, key []byte) ([]byte, error) {
+	var value []byte
+	err := db.View(func(tx *bbolt.Tx) error {
+		b := tx.Bucket(defaultBucket)
+		if b == nil {
+			return ErrNoDefaultBucket
+		}
+		value = b.Get(key)
+		if value == nil {
+			return object.ErrNotFound
+		}
+		value = cloneBytes(value)
+		return nil
+	})
+	return value, err
+}