Index: src/wp-includes/ms-load.php
===================================================================
--- src/wp-includes/ms-load.php	(revision 38348)
+++ src/wp-includes/ms-load.php	(working copy)
@@ -156,13 +156,14 @@
  * Retrieve a site object by its domain and path.
  *
  * @since 3.9.0
+ * @since 4.7.0 Now always returns a `WP_Site` object.
  *
  * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param string   $domain   Domain to check.
  * @param string   $path     Path to check.
  * @param int|null $segments Path segments to use. Defaults to null, or the full path.
- * @return object|false Site object if successful. False when no site is found.
+ * @return WP_Site|false Site object if successful. False when no site is found.
  */
 function get_site_by_path( $domain, $path, $segments = null ) {
 	$path_segments = array_filter( explode( '/', trim( $path, '/' ) ) );
@@ -205,15 +206,18 @@
 	 *
 	 * @since 3.9.0
 	 *
-	 * @param null|bool|object $site     Site value to return by path.
-	 * @param string           $domain   The requested domain.
-	 * @param string           $path     The requested path, in full.
-	 * @param int|null         $segments The suggested number of paths to consult.
-	 *                                   Default null, meaning the entire path was to be consulted.
-	 * @param array            $paths    The paths to search for, based on $path and $segments.
+	 * @param null|bool|WP_Site $site     Site value to return by path.
+	 * @param string            $domain   The requested domain.
+	 * @param string            $path     The requested path, in full.
+	 * @param int|null          $segments The suggested number of paths to consult.
+	 *                                    Default null, meaning the entire path was to be consulted.
+	 * @param array             $paths    The paths to search for, based on $path and $segments.
 	 */
 	$pre = apply_filters( 'pre_get_site_by_path', null, $domain, $path, $segments, $paths );
 	if ( null !== $pre ) {
+		if ( false !== $pre && ! $pre instanceof WP_Site ) {
+			$pre = new WP_Site( $pre );
+		}
 		return $pre;
 	}
 
@@ -251,7 +255,6 @@
 	$site = array_shift( $result );
 
 	if ( $site ) {
-		// @todo get_blog_details()
 		return $site;
 	}
 
Index: tests/phpunit/tests/multisite/bootstrap.php
===================================================================
--- tests/phpunit/tests/multisite/bootstrap.php	(revision 38348)
+++ tests/phpunit/tests/multisite/bootstrap.php	(working copy)
@@ -208,9 +208,32 @@
 		$this->assertEqualSetsWithIndex( $expected, $actual );
 	}
 
+	/**
+	 * @ticket 37053
+	 */
+	public function test_get_site_by_path_returns_wp_site() {
+		add_filter( 'pre_get_site_by_path', array( $this, 'filter_pre_get_site_by_path' ), 10, 3 );
+
+		$site = get_site_by_path( 'example.com', '/foo/' );
+
+		remove_filter( 'pre_get_site_by_path', array( $this, 'filter_pre_get_site_by_path' ), 10 );
+
+		$this->assertInstanceOf( 'WP_Site', $site );
+	}
+
 	public function filter_path_segments_to_two() {
 		return 2;
 	}
+
+	public function filter_pre_get_site_by_path( $site, $domain, $path ) {
+		$site = new stdClass();
+		$site->blog_id = 100;
+		$site->domain = $domain;
+		$site->path = $path;
+		$site->site_id = 1;
+
+		return $site;
+	}
 }
 
 endif;
