diff --git src/js/_enqueues/wp/util.js src/js/_enqueues/wp/util.js
index b5ba1801d7..8384371173 100644
--- src/js/_enqueues/wp/util.js
+++ src/js/_enqueues/wp/util.js
@@ -115,7 +115,7 @@ window.wp = window.wp || {};
 					}
 
 					if ( _.isObject( response ) && ! _.isUndefined( response.success ) ) {
-						deferred[ response.success ? 'resolveWith' : 'rejectWith' ]( this, [response.data] );
+						deferred[ response.success ? 'resolveWith' : 'rejectWith' ]( deferred.jqXHR, [response.data] );
 					} else {
 						deferred.rejectWith( this, [response] );
 					}
diff --git src/js/media/models/attachments.js src/js/media/models/attachments.js
index a0ba72869b..f4b4e48297 100644
--- src/js/media/models/attachments.js
+++ src/js/media/models/attachments.js
@@ -375,21 +375,15 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen
 	 * passing through the JSON response. We override this to add attributes to
 	 * the collection items.
 	 *
-	 * @since 5.8.0 The response returns the attachments under `response.attachments` and
-	 *              `response.totalAttachments` holds the total number of attachments found.
-	 *
 	 * @param {Object|Array} response The raw response Object/Array.
 	 * @param {Object} xhr
 	 * @return {Array} The array of model attributes to be added to the collection
 	 */
 	parse: function( response, xhr ) {
-		if ( ! _.isArray( response.attachments ) ) {
-			response = [ response.attachments ];
+		if ( ! _.isArray( response ) ) {
+			  response = [response];
 		}
-
-		this.totalAttachments = parseInt( response.totalAttachments, 10 );
-
-		return _.map( response.attachments, function( attrs ) {
+		return _.map( response, function( attrs ) {
 			var id, attachment, newAttributes;
 
 			if ( attrs instanceof Backbone.Model ) {
@@ -409,9 +403,20 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen
 			return attachment;
 		});
 	},
+
+	// Customize fetch so we can extract the total post count from the response headers.
+	fetch: function(options) {
+		var collection = this;
+		var fetched = Backbone.Collection.prototype.fetch.call(this, options)
+			.done( function() {
+				collection.totalAttachments = parseInt( this.getResponseHeader( 'X-WP-Total' ), 10 );
+			} );
+		return fetched;
+	},
+
 	/**
 	 * If the collection is a query, create and mirror an Attachments Query collection.
-	 * 
+	 *
 	 * @access private
 	 * @param {Boolean} refresh Deprecated, refresh parameter no longer used.
 	 */
diff --git src/js/media/models/query.js src/js/media/models/query.js
index d744537c44..1d56fed624 100644
--- src/js/media/models/query.js
+++ src/js/media/models/query.js
@@ -113,9 +113,7 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{
 		options.remove = false;
 
 		return this._more = this.fetch( options ).done( function( response ) {
-			var attachments = response.attachments;
-
-			if ( _.isEmpty( attachments ) || -1 === this.args.posts_per_page || attachments.length < this.args.posts_per_page ) {
+			if ( _.isEmpty( response ) || -1 === query.args.posts_per_page || response.length < query.args.posts_per_page ) {
 				query._hasMore = false;
 			}
 		});
diff --git src/js/media/views/attachments/browser.js src/js/media/views/attachments/browser.js
index 6a75fb9a7d..4f7625cfe3 100644
--- src/js/media/views/attachments/browser.js
+++ src/js/media/views/attachments/browser.js
@@ -635,11 +635,10 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
 		});
 
 		view.loadMoreSpinner.show();
-
-		this.collection.more().done( function() {
-			// Within done(), `this` is the returned collection.
+		this.collection.once( 'attachments:received', function() {
 			view.loadMoreSpinner.hide();
 		} );
+		this.collection.more();
 	},
 
 	/**
diff --git src/wp-admin/includes/ajax-actions.php src/wp-admin/includes/ajax-actions.php
index feb35ca40c..32e777e569 100644
--- src/wp-admin/includes/ajax-actions.php
+++ src/wp-admin/includes/ajax-actions.php
@@ -2990,17 +2990,27 @@ function wp_ajax_query_attachments() {
 	 * @param array $query An array of query variables.
 	 */
 	$query = apply_filters( 'ajax_query_attachments_args', $query );
-	$query = new WP_Query( $query );
+	$attachments_query = new WP_Query( $query );
 
-	$posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
+	$posts = array_map( 'wp_prepare_attachment_for_js', $attachments_query->posts );
 	$posts = array_filter( $posts );
+	$total_posts = $attachments_query->found_posts;
 
-	$result = array(
-		'attachments'      => $posts,
-		'totalAttachments' => $query->found_posts,
-	);
+	if ( $total_posts < 1 ) {
+		// Out-of-bounds, run the query again without LIMIT for total count.
+		unset( $query['paged'] );
+
+		$count_query = new WP_Query();
+		$count_query->query( $query_args );
+		$total_posts = $count_query->found_posts;
+	}
+
+	$max_pages = ceil( $total_posts / (int) $attachments_query->query['posts_per_page'] );
+
+	header( 'X-WP-Total: ' . (int) $total_posts );
+	header( 'X-WP-TotalPages: ' . (int) $max_pages );
 
-	wp_send_json_success( $result );
+	wp_send_json_success( $posts );
 }
 
 /**
