diff --git a/cmd/starcoin/src/chain/get_block_cmd.rs b/cmd/starcoin/src/chain/get_block_cmd.rs
index d2c2f6d1fd..41419425b5 100644
--- a/cmd/starcoin/src/chain/get_block_cmd.rs
+++ b/cmd/starcoin/src/chain/get_block_cmd.rs
@@ -23,6 +23,9 @@ pub enum HashOrNumber {
 pub struct GetBlockOpt {
     #[clap(name = "hash-or-number")]
     hash_or_number: HashOrNumber,
+
+    #[clap(name = "contains-raw-body")]
+    raw_body: bool,
 }
 
 impl FromStr for HashOrNumber {
@@ -52,10 +55,22 @@ impl CommandAction for GetBlockCommand {
         let opt = ctx.opt();
         let block = match opt.hash_or_number {
             HashOrNumber::Hash(hash) => client
-                .chain_get_block_by_hash(hash, Some(GetBlockOption { decode: true }))?
+                .chain_get_block_by_hash(
+                    hash,
+                    Some(GetBlockOption {
+                        decode: true,
+                        raw: opt.raw_body,
+                    }),
+                )?
                 .ok_or_else(|| anyhow::format_err!("block of hash {} not found", hash))?,
             HashOrNumber::Number(number) => client
-                .chain_get_block_by_number(number, Some(GetBlockOption { decode: true }))?
+                .chain_get_block_by_number(
+                    number,
+                    Some(GetBlockOption {
+                        decode: true,
+                        raw: opt.raw_body,
+                    }),
+                )?
                 .ok_or_else(|| anyhow::format_err!("block of height {} not found", number))?,
         };
         Ok(block)
diff --git a/rpc/api/src/chain/mod.rs b/rpc/api/src/chain/mod.rs
index 293969c776..7ec60573d2 100644
--- a/rpc/api/src/chain/mod.rs
+++ b/rpc/api/src/chain/mod.rs
@@ -123,6 +123,9 @@ pub struct GetTransactionOption {
 pub struct GetBlockOption {
     #[serde(default)]
     pub decode: bool,
+
+    #[serde(default)]
+    pub raw: bool,
 }
 
 #[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)]
diff --git a/rpc/api/src/types.rs b/rpc/api/src/types.rs
index bd0f763363..710a81fc41 100644
--- a/rpc/api/src/types.rs
+++ b/rpc/api/src/types.rs
@@ -749,11 +749,17 @@ pub struct BlockView {
     pub header: BlockHeaderView,
     pub body: BlockTransactionsView,
     pub uncles: Vec<BlockHeaderView>,
+    pub raw_body: Option<String>,
 }
 
 impl BlockView {
-    pub fn try_from_block(block: Block, thin: bool) -> Result<Self, anyhow::Error> {
+    pub fn try_from_block(block: Block, thin: bool, raw: bool) -> Result<Self, anyhow::Error> {
         let (header, body) = block.into_inner();
+        let raw_body = if raw {
+            Some(hex::encode(bcs_ext::to_bytes(&body)?))
+        } else {
+            None
+        };
         let BlockBody {
             transactions,
             uncles,
@@ -771,6 +777,7 @@ impl BlockView {
                 .map(|h| h.into())
                 .collect(),
             body: txns_view,
+            raw_body,
         })
     }
 }
@@ -779,7 +786,7 @@ impl TryFrom<Block> for BlockView {
     type Error = anyhow::Error;
 
     fn try_from(block: Block) -> Result<Self, Self::Error> {
-        Self::try_from_block(block, false)
+        Self::try_from_block(block, false, false)
     }
 }
 
diff --git a/rpc/generated_rpc_schema/chain.json b/rpc/generated_rpc_schema/chain.json
index 3a8ba542f8..26497de657 100644
--- a/rpc/generated_rpc_schema/chain.json
+++ b/rpc/generated_rpc_schema/chain.json
@@ -265,6 +265,10 @@
               "decode": {
                 "default": false,
                 "type": "boolean"
+              },
+              "raw": {
+                "default": false,
+                "type": "boolean"
               }
             }
           }
@@ -664,6 +668,12 @@
                 }
               }
             },
+            "raw_body": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
             "uncles": {
               "type": "array",
               "items": {
@@ -791,6 +801,10 @@
               "decode": {
                 "default": false,
                 "type": "boolean"
+              },
+              "raw": {
+                "default": false,
+                "type": "boolean"
               }
             }
           }
@@ -1190,6 +1204,12 @@
                 }
               }
             },
+            "raw_body": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
             "uncles": {
               "type": "array",
               "items": {
@@ -1711,6 +1731,12 @@
                   }
                 }
               },
+              "raw_body": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              },
               "uncles": {
                 "type": "array",
                 "items": {
diff --git a/rpc/server/src/module/chain_rpc.rs b/rpc/server/src/module/chain_rpc.rs
index 5aa3224f48..ceb6578e9a 100644
--- a/rpc/server/src/module/chain_rpc.rs
+++ b/rpc/server/src/module/chain_rpc.rs
@@ -83,10 +83,13 @@ where
     ) -> FutureResult<Option<BlockView>> {
         let service = self.service.clone();
         let decode = option.unwrap_or_default().decode;
+        let raw = option.unwrap_or_default().raw;
         let storage = self.storage.clone();
         let fut = async move {
             let result = service.get_block_by_hash(hash).await?;
-            let mut block: Option<BlockView> = result.map(|b| b.try_into()).transpose()?;
+            let mut block: Option<BlockView> = result
+                .map(|b| BlockView::try_from_block(b, false, raw))
+                .transpose()?;
             if decode {
                 let state = ChainStateDB::new(
                     storage,
@@ -110,11 +113,14 @@ where
     ) -> FutureResult<Option<BlockView>> {
         let service = self.service.clone();
         let decode = option.unwrap_or_default().decode;
+        let raw = option.unwrap_or_default().raw;
         let storage = self.storage.clone();
 
         let fut = async move {
             let result = service.main_block_by_number(number).await?;
-            let mut block: Option<BlockView> = result.map(|b| b.try_into()).transpose()?;
+            let mut block: Option<BlockView> = result
+                .map(|b| BlockView::try_from_block(b, false, raw))
+                .transpose()?;
             if decode {
                 let state = ChainStateDB::new(
                     storage,
@@ -153,7 +159,7 @@ where
 
             block
                 .into_iter()
-                .map(|blk| BlockView::try_from_block(blk, true))
+                .map(|blk| BlockView::try_from_block(blk, true, false))
                 .collect::<Result<Vec<_>, _>>()
         }
         .map_err(map_err);
diff --git a/rpc/server/src/module/pubsub.rs b/rpc/server/src/module/pubsub.rs
index b242cba42c..a3c707ebda 100644
--- a/rpc/server/src/module/pubsub.rs
+++ b/rpc/server/src/module/pubsub.rs
@@ -499,6 +499,7 @@ impl EventHandler<Notification<ThinBlock>> for NewHeadHandler {
             header: block.header.into(),
             body: block.body.into(),
             uncles: vec![],
+            raw_body: None,
         })))]
     }
 }