diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 15c9b2d97d6df4e6f37297a0e9d9e08005ac8c8b..b647735ead71f43333c2fddbfd04954f6bd1c990 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -453,6 +453,8 @@ void Call::Init(Handle<Object> exports) {
                           NanNew<FunctionTemplate>(StartBatch)->GetFunction());
   NanSetPrototypeTemplate(tpl, "cancel",
                           NanNew<FunctionTemplate>(Cancel)->GetFunction());
+  NanSetPrototypeTemplate(tpl, "getPeer",
+                          NanNew<FunctionTemplate>(GetPeer)->GetFunction());
   NanAssignPersistent(fun_tpl, tpl);
   Handle<Function> ctr = tpl->GetFunction();
   ctr->Set(NanNew("WRITE_BUFFER_HINT"),
@@ -608,5 +610,17 @@ NAN_METHOD(Call::Cancel) {
   NanReturnUndefined();
 }
 
+NAN_METHOD(Call::GetPeer) {
+  NanScope();
+  if (!HasInstance(args.This())) {
+    return NanThrowTypeError("getPeer can only be called on Call objects");
+  }
+  Call *call = ObjectWrap::Unwrap<Call>(args.This());
+  char *peer = grpc_call_get_peer(call->wrapped_call);
+  Handle<Value> peer_value = NanNew(peer);
+  gpr_free(peer);
+  NanReturnValue(peer_value);
+}
+
 }  // namespace node
 }  // namespace grpc
diff --git a/src/node/ext/call.h b/src/node/ext/call.h
index 43142c7091fe6c30b434a03d413c22f844853771..6acda76197ffcac36af764ba5c83e5a6c7df510c 100644
--- a/src/node/ext/call.h
+++ b/src/node/ext/call.h
@@ -120,6 +120,7 @@ class Call : public ::node::ObjectWrap {
   static NAN_METHOD(New);
   static NAN_METHOD(StartBatch);
   static NAN_METHOD(Cancel);
+  static NAN_METHOD(GetPeer);
   static NanCallback *constructor;
   // Used for typechecking instances of this javascript class
   static v8::Persistent<v8::FunctionTemplate> fun_tpl;
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index d37bf763ddc707396783576ac2753bc6e3ef2d30..0b7333e45025a3852c4cca9044a780baf3a1f275 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -76,6 +76,8 @@ void Channel::Init(Handle<Object> exports) {
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
   NanSetPrototypeTemplate(tpl, "close",
                           NanNew<FunctionTemplate>(Close)->GetFunction());
+  NanSetPrototypeTemplate(tpl, "getTarget",
+                          NanNew<FunctionTemplate>(GetTarget)->GetFunction());
   NanAssignPersistent(fun_tpl, tpl);
   Handle<Function> ctr = tpl->GetFunction();
   constructor = new NanCallback(ctr);
@@ -185,5 +187,14 @@ NAN_METHOD(Channel::Close) {
   NanReturnUndefined();
 }
 
+NAN_METHOD(Channel::GetTarget) {
+  NanScope();
+  if (!HasInstance(args.This())) {
+    return NanThrowTypeError("getTarget can only be called on Channel objects");
+  }
+  Channel *channel = ObjectWrap::Unwrap<Channel>(args.This());
+  NanReturnValue(NanNew(grpc_channel_get_target(channel->wrapped_channel)));
+}
+
 }  // namespace node
 }  // namespace grpc
diff --git a/src/node/ext/channel.h b/src/node/ext/channel.h
index b3aa0f700fa98b16f47a4fa6bd4834b0f550a600..6725ebb03f008262f7a76a5d30c5efece74732d6 100644
--- a/src/node/ext/channel.h
+++ b/src/node/ext/channel.h
@@ -66,6 +66,7 @@ class Channel : public ::node::ObjectWrap {
 
   static NAN_METHOD(New);
   static NAN_METHOD(Close);
+  static NAN_METHOD(GetTarget);
   static NanCallback *constructor;
   static v8::Persistent<v8::FunctionTemplate> fun_tpl;
 
diff --git a/src/node/src/client.js b/src/node/src/client.js
index da6327b4320461f123943b8a2fabccdb0ed38f77..d89c656c07e6c7be24beb4efd814004236a1947d 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -187,6 +187,19 @@ ClientReadableStream.prototype.cancel = cancel;
 ClientWritableStream.prototype.cancel = cancel;
 ClientDuplexStream.prototype.cancel = cancel;
 
+/**
+ * Get the endpoint this call/stream is connected to.
+ * @return {string} The URI of the endpoint
+ */
+function getPeer() {
+  /* jshint validthis: true */
+  return this.call.getPeer();
+}
+
+ClientReadableStream.prototype.getPeer = getPeer;
+ClientWritableStream.prototype.getPeer = getPeer;
+ClientDuplexStream.prototype.getPeer = getPeer;
+
 /**
  * Get a function that can make unary requests to the specified method.
  * @param {string} method The name of the method to request
@@ -223,6 +236,9 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
     emitter.cancel = function cancel() {
       call.cancel();
     };
+    emitter.getPeer = function getPeer() {
+      return call.getPeer();
+    };
     this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
       if (error) {
         call.cancel();
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 0a3a0031bdfad75d47914e5688a8d0907d92555f..cb86b95f381e34b54001de3eae9f231b2d3ba8f3 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -373,6 +373,19 @@ ServerDuplexStream.prototype._read = _read;
 ServerDuplexStream.prototype._write = _write;
 ServerDuplexStream.prototype.sendMetadata = sendMetadata;
 
+/**
+ * Get the endpoint this call/stream is connected to.
+ * @return {string} The URI of the endpoint
+ */
+function getPeer() {
+  /* jshint validthis: true */
+  return this.call.getPeer();
+}
+
+ServerReadableStream.prototype.getPeer = getPeer;
+ServerWritableStream.prototype.getPeer = getPeer;
+ServerDuplexStream.prototype.getPeer = getPeer;
+
 /**
  * Fully handle a unary call
  * @param {grpc.Call} call The call to handle
@@ -389,6 +402,9 @@ function handleUnary(call, handler, metadata) {
       call.startBatch(batch, function() {});
     }
   };
+  emitter.getPeer = function() {
+    return call.getPeer();
+  };
   emitter.on('error', function(error) {
     handleError(call, error);
   });
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index 98158ffff357d0efed892e8c91d6c8851d7c7d4e..0079144ae6d78e94ed971f95fbe8e0a45d34eb89 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -184,4 +184,10 @@ describe('call', function() {
       });
     });
   });
+  describe('getPeer', function() {
+    it('should return a string', function() {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      assert.strictEqual(typeof call.getPeer(), 'string');
+    });
+  });
 });
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index 33200c99ee2d8f3305d9efa703c2cbd28ddf4ea4..3e61d3bbc62da47cad37b75e7b7ea9817c864477 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -87,4 +87,10 @@ describe('channel', function() {
       });
     });
   });
+  describe('getTarget', function() {
+    it('should return a string', function() {
+      var channel = new grpc.Channel('localhost', {});
+      assert.strictEqual(typeof channel.getTarget(), 'string');
+    });
+  });
 });
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 3cb68f8cd8389fe9b0d3b4e5ba33cb2313fce13b..9005cbd505a7fbc7532882cc3eea3b9bdaa19620 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -344,6 +344,9 @@ describe('Other conditions', function() {
   after(function() {
     server.shutdown();
   });
+  it('channel.getTarget should be available', function() {
+    assert.strictEqual(typeof client.channel.getTarget(), 'string');
+  });
   describe('Server recieving bad input', function() {
     var misbehavingClient;
     var badArg = new Buffer([0xFF]);
@@ -549,6 +552,43 @@ describe('Other conditions', function() {
       });
     });
   });
+  describe('call.getPeer should return the peer', function() {
+    it('for a unary call', function(done) {
+      var call = client.unary({error: false}, function(err, data) {
+        assert.ifError(err);
+        done();
+      });
+      assert.strictEqual(typeof call.getPeer(), 'string');
+    });
+    it('for a client stream call', function(done) {
+      var call = client.clientStream(function(err, data) {
+        assert.ifError(err);
+        done();
+      });
+      assert.strictEqual(typeof call.getPeer(), 'string');
+      call.write({error: false});
+      call.end();
+    });
+    it('for a server stream call', function(done) {
+      var call = client.serverStream({error: false});
+      assert.strictEqual(typeof call.getPeer(), 'string');
+      call.on('data', function(){});
+      call.on('status', function(status) {
+        assert.strictEqual(status.code, grpc.status.OK);
+        done();
+      });
+    });
+    it('for a bidi stream call', function(done) {
+      var call = client.bidiStream();
+      assert.strictEqual(typeof call.getPeer(), 'string');
+      call.write({error: false});
+      call.end();
+      call.on('data', function(){});
+      call.on('status', function(status) {
+        done();
+      });
+    });
+  });
 });
 describe('Cancelling surface client', function() {
   var client;