diff --git a/package-lock.json b/package-lock.json
index f1bf389..8bf3f03 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7067,8 +7067,8 @@
             }
         },
         "lbry-redux": {
-            "version": "github:lbryio/lbry-redux#e8f29f1c47b136669df265babb109d2488a37db0",
-            "from": "github:lbryio/lbry-redux#e8f29f1c47b136669df265babb109d2488a37db0",
+            "version": "github:lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
+            "from": "github:lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
             "requires": {
                 "proxy-polyfill": "0.1.6",
                 "reselect": "^3.0.0",
diff --git a/package.json b/package.json
index a211509..5a6745b 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
         "base-64": "^0.1.0",
         "@expo/vector-icons": "^8.1.0",
         "gfycat-style-urls": "^1.0.3",
-        "lbry-redux": "lbryio/lbry-redux#e8f29f1c47b136669df265babb109d2488a37db0",
+        "lbry-redux": "lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
         "lbryinc": "lbryio/lbryinc#053ca52f4f7f9bf8eb62a3581b183671a475ad1c",
         "lodash": ">=4.17.11",
         "merge": ">=1.2.1",
diff --git a/src/page/search/index.js b/src/page/search/index.js
index 339a0e4..edb4b1f 100644
--- a/src/page/search/index.js
+++ b/src/page/search/index.js
@@ -5,6 +5,7 @@ import {
   doResolvedSearch,
   doUpdateSearchQuery,
   makeSelectResolvedSearchResults,
+  makeSelectResolvedSearchResultsLastPageReached,
   makeSelectSearchUris,
   selectClaimSearchByQuery,
   selectIsSearching,
@@ -17,20 +18,21 @@ import { selectCurrentRoute } from 'redux/selectors/drawer';
 import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
 import SearchPage from './view';
 
-const numSearchResults = 25;
-
 const select = state => ({
   claimSearchByQuery: selectClaimSearchByQuery(state),
   currentRoute: selectCurrentRoute(state),
   isSearching: selectIsSearching(state),
   query: selectSearchValue(state),
   resolvingUris: selectResolvingUris(state),
-  uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, numSearchResults)(state))(state),
-  results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, numSearchResults)(state))(state),
+  uris: makeSelectSearchUris(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
+  results: makeSelectResolvedSearchResults(makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state))(state),
+  lastPageReached: makeSelectResolvedSearchResultsLastPageReached(
+    makeSelectQueryWithOptions(null, Constants.DEFAULT_PAGE_SIZE)(state),
+  )(state),
 });
 
 const perform = dispatch => ({
-  search: query => dispatch(doResolvedSearch(query, numSearchResults, null, false, {})),
+  search: (query, from) => dispatch(doResolvedSearch(query, Constants.DEFAULT_PAGE_SIZE, from, false, {})),
   claimSearch: options => dispatch(doClaimSearch(options)),
   updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
   pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SEARCH)),
diff --git a/src/page/search/view.js b/src/page/search/view.js
index 5747637..7710b3e 100644
--- a/src/page/search/view.js
+++ b/src/page/search/view.js
@@ -20,9 +20,12 @@ import FloatingWalletBalance from 'component/floatingWalletBalance';
 import UriBar from 'component/uriBar';
 import searchStyle from 'styles/search';
 
+const softLimit = 500;
+
 class SearchPage extends React.PureComponent {
   state = {
     currentQuery: null,
+    currentFrom: 0,
     currentUri: null,
     showTagResult: false,
     claimSearchRun: false,
@@ -56,6 +59,7 @@ class SearchPage extends React.PureComponent {
       const searchQuery = query || this.getSearchQuery();
       if (searchQuery && searchQuery.trim().length > 0) {
         this.setState({
+          currentFrom: 0,
           currentQuery: searchQuery,
           currentUri: isURIValid(searchQuery) ? normalizeURI(searchQuery) : null,
           claimSearchOptions: null,
@@ -64,7 +68,7 @@ class SearchPage extends React.PureComponent {
           resultsResolved: false,
           tagResultDisplayed: false,
         });
-        search(searchQuery);
+        search(searchQuery, 0);
       }
     });
   };
@@ -83,12 +87,13 @@ class SearchPage extends React.PureComponent {
 
     if (query && query.trim().length > 0 && query !== this.state.currentQuery) {
       this.setState({
+        currentFrom: 0,
         currentQuery: query,
         currentUri: isURIValid(query) ? normalizeURI(query) : null,
         resultsResolved: false,
         tagResultDisplayed: false,
       });
-      search(query);
+      search(query, 0);
     }
   }
 
@@ -134,13 +139,15 @@ class SearchPage extends React.PureComponent {
     const { search } = this.props;
     this.setState({
       currentUri: isURIValid(keywords) ? normalizeURI(keywords) : null,
+      currentFrom: 0,
+      currentQuery: keywords,
       claimSearchOptions: null,
       claimSearchRun: false,
       showTagResult: false,
       resultsResolved: false,
       tagResultDisplayed: false,
     });
-    search(keywords);
+    search(keywords, 0);
   };
 
   listEmptyComponent = () => {
@@ -186,6 +193,21 @@ class SearchPage extends React.PureComponent {
     navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: `tagPage`, params: { tag: tag.toLowerCase() } });
   };
 
+  handleVerticalEndReached = () => {
+    // fetch more results
+    const { lastPageReached, results, search, isSearching } = this.props;
+    if (lastPageReached || (results && results.length > softLimit)) {
+      return;
+    }
+
+    if (!isSearching) {
+      const from = results ? results.length : 0;
+      this.setState({ currentFrom: from }, () => {
+        search(this.state.currentQuery, from);
+      });
+    }
+  };
+
   render() {
     const { isSearching, navigation, query, results } = this.props;
 
@@ -193,13 +215,13 @@ class SearchPage extends React.PureComponent {
       <View style={searchStyle.container}>
         <UriBar value={query} navigation={navigation} onSearchSubmitted={this.handleSearchSubmitted} />
 
-        {isSearching && (
+        {isSearching && this.state.currentFrom === 0 && (
           <View style={searchStyle.busyContainer}>
             <ActivityIndicator size="large" color={Colors.NextLbryGreen} style={searchStyle.loading} />
           </View>
         )}
 
-        {!isSearching && (
+        {(!isSearching || this.state.currentFrom > 0) && (
           <FlatList
             extraData={this.state}
             style={searchStyle.scrollContainer}
@@ -207,8 +229,10 @@ class SearchPage extends React.PureComponent {
             keyboardShouldPersistTaps={'handled'}
             data={results}
             keyExtractor={(item, index) => item.claimId}
-            initialNumToRender={8}
+            initialNumToRender={10}
             maxToRenderPerBatch={20}
+            onEndReached={this.handleVerticalEndReached}
+            onEndReachedThreshold={0.2}
             removeClippedSubviews
             ListEmptyComponent={!isSearching ? this.listEmptyComponent() : null}
             ListHeaderComponent={this.listHeaderComponent(this.state.showTagResult, this.state.currentQuery)}
@@ -217,6 +241,11 @@ class SearchPage extends React.PureComponent {
             )}
           />
         )}
+        {this.state.currentFrom > 0 && isSearching && (
+          <View style={searchStyle.moreLoading}>
+            <ActivityIndicator size="small" color={Colors.NextLbryGreen} />
+          </View>
+        )}
         <FloatingWalletBalance navigation={navigation} />
       </View>
     );
diff --git a/src/styles/search.js b/src/styles/search.js
index 4321f9e..b57373a 100644
--- a/src/styles/search.js
+++ b/src/styles/search.js
@@ -80,6 +80,12 @@ const searchStyle = StyleSheet.create({
   loading: {
     position: 'absolute',
   },
+  moreLoading: {
+    width: '100%',
+    height: 48,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
 });
 
 export default searchStyle;