diff --git a/public/src/forum/category.js b/public/src/forum/category.js
index aa6b25dd79..b0dff6f486 100644
--- a/public/src/forum/category.js
+++ b/public/src/forum/category.js
@@ -52,24 +52,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
 				}
 			});
 		} else {
-			pagination.init(templates.get('currentPage'), templates.get('pageCount'), loadPage);
+			pagination.init(templates.get('currentPage'), templates.get('pageCount'));
 		}
 	}
 
-	function loadPage(page, callback) {
-		socket.emit('categories.loadPage', {cid: templates.get('category_id'), page: page}, function(err, data) {
-			if(err) {
-				return callback(err);
-			}
-
-			if (data && data.topics && data.topics.length) {
-				Category.onTopicsLoaded(data.topics);
-			}
-
-			callback(null);
-		});
-	}
-
 	Category.onNewTopic = function(data) {
 		var html = templates.prepare(templates['category'].blocks['topics']).parse({
 			topics: [data]
diff --git a/public/src/forum/pagination.js b/public/src/forum/pagination.js
index d7e9abc965..7c21a3090d 100644
--- a/public/src/forum/pagination.js
+++ b/public/src/forum/pagination.js
@@ -5,12 +5,10 @@ define(function() {
 
 	pagination.currentPage = 0;
 	pagination.pageCount = 0;
-	pagination.loadFunction = null;
 
-	pagination.init = function(currentPage, pageCount, loadFunction) {
+	pagination.init = function(currentPage, pageCount) {
 		pagination.currentPage = parseInt(currentPage, 10);
 		pagination.pageCount = parseInt(pageCount, 10);
-		pagination.loadFunction = loadFunction;
 
 		updatePageLinks();
 
@@ -48,17 +46,9 @@ define(function() {
 			return;
 		}
 
-		pagination.loadFunction(page, function(err) {
-			if(err) {
-				return app.alertError(err.message);
-			}
-
-			pagination.currentPage = parseInt(page, 10);
-			updatePageLinks();
-		});
+		ajaxify.go(window.location.pathname.slice(1) + '?page=' + page);
 	}
 
-
 	function updatePageLinks() {
 		if(pagination.pageCount === 0) {
 			$('.pagination').addClass('hide');
@@ -79,6 +69,11 @@ define(function() {
 
 		$('.pagination .page').removeClass('active');
 		$('.pagination .page[data-page="' + pagination.currentPage + '"]').addClass('active');
+		$('.pagination .page').each(function(index, element) {
+			var li = $(this);
+			var page = li.attr('data-page');
+			li.find('a').attr('href', window.location.pathname + '?page=' + page);
+		});
 	}
 
 	return pagination;
diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js
index 60ab01ce92..3976687684 100644
--- a/public/src/forum/topic.js
+++ b/public/src/forum/topic.js
@@ -4,8 +4,8 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
 		pagination;
 
 	function showBottomPostBar() {
-		if($('#post-container .post-row').length > 1) {
-			$('.topic-main-buttons').removeClass('hide').parent().removeClass('hide');
+		if($('#post-container .post-row').length > 1 || !$('#post-container li[data-index="0"]').length) {
+			$('.bottom-post-bar').removeClass('hide');
 		}
 	}
 
@@ -328,7 +328,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
 
 			var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
 
-			if(bookmark && !config.usePagination) {
+			if(bookmark) {
 				Topic.scrollToPost(parseInt(bookmark, 10));
 			}
 
@@ -358,65 +358,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
 			} else {
 				$('.pagination-block').addClass('hide');
 
-				pagination.init(currentPage, pageCount, loadPage);
+				pagination.init(currentPage, pageCount);
 			}
 		}
 
-		function loadPage(page, callback) {
-			if(page === 1) {
-				ajaxify.go('topic/' + tid );
-				return;
-			}
-
-			socket.emit('topics.loadPage', {tid: tid, page: page}, function(err, data) {
-				if(err) {
-					return callback(err);
-				}
-
-				if (data && data.posts && data.posts.length) {
-					createPagePosts(data, function() {
-						fixDeleteStateForPosts();
-					});
-				}
-
-				callback(null);
-			});
-		}
-
-		function onNewPostPagination(data) {
-			var posts = data.posts;
-			socket.emit('topics.getPageCount', tid, function(err, newPageCount) {
-
-				pagination.recreatePaginationLinks('topic', newPageCount);
-
-				if(pagination.currentPage === pagination.newPageCount) {
-					createNewPosts(data);
-				} else if(data.posts && data.posts.length && parseInt(data.posts[0].uid, 10) === parseInt(app.uid, 10)) {
-					pagination.loadPage(pagination.pageCount);
-				}
-			});
-		}
-
-		function createPagePosts(data, callback) {
-			if(!data || (data.posts && !data.posts.length)) {
-				return;
-			}
-
-			parseAndTranslatePosts(data.posts, function(translatedHTML) {
-				var translated = $(translatedHTML);
-
-				$('#post-container').fadeOut(200, function() {
-
-					$('#post-container').empty().append(translated).fadeIn('slow');
-
-					onNewPostsLoaded(data.posts);
-
-					callback();
-				});
-			});
-		}
-
-
 		$('.topic').on('click', '.post_reply', function() {
 			var selectionText = '',
 				selection = window.getSelection() || document.getSelection();
@@ -1071,36 +1016,64 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
 			return;
 		}
 
-		var container = $(window),
+		if(config.usePagination) {
+			socket.emit('posts.getPidPage', pid, function(err, page) {
+				if(parseInt(page, 10) !== pagination.currentPage) {
+					pagination.loadPage(page);
+				} else {
+					scrollToPid(pid);
+				}
+			});
+		} else {
+			scrollToPid(pid);
+		}
+
+		function scrollToPid(pid) {
+			var container = $(window),
 			scrollTo = $('#post_anchor_' + pid),
 			tid = $('#post-container').attr('data-tid');
 
-		function animateScroll() {
-			$('window,html').animate({
-				scrollTop: scrollTo.offset().top + container.scrollTop() - $('#header-menu').height()
-			}, 400);
-		}
+			function animateScroll() {
+				$('window,html').animate({
+					scrollTop: scrollTo.offset().top + container.scrollTop() - $('#header-menu').height()
+				}, 400);
+			}
 
-		if (!scrollTo.length && tid) {
+			if (!scrollTo.length && tid) {
 
-			var intervalID = setInterval(function () {
-				loadMorePosts(tid, function (posts) {
-					scrollTo = $('#post_anchor_' + pid);
+				var intervalID = setInterval(function () {
+					loadMorePosts(tid, function (posts) {
+						scrollTo = $('#post_anchor_' + pid);
 
-					if (tid && scrollTo.length) {
-						animateScroll();
-					}
+						if (tid && scrollTo.length) {
+							animateScroll();
+						}
 
-					if (!posts.length || scrollTo.length)
-						clearInterval(intervalID);
-				});
-			}, 100);
+						if (!posts.length || scrollTo.length)
+							clearInterval(intervalID);
+					});
+				}, 100);
 
-		} else if (tid) {
-			animateScroll();
+			} else if (tid) {
+				animateScroll();
+			}
 		}
 	}
 
+	function onNewPostPagination(data) {
+		var posts = data.posts;
+		socket.emit('topics.getPageCount', tid, function(err, newPageCount) {
+
+			pagination.recreatePaginationLinks('topic', newPageCount);
+
+			if(pagination.currentPage === pagination.pageCount) {
+				createNewPosts(data);
+			} else if(data.posts && data.posts.length && parseInt(data.posts[0].uid, 10) === parseInt(app.uid, 10)) {
+				pagination.loadPage(pagination.pageCount);
+			}
+		});
+	}
+
 	function createNewPosts(data, infiniteLoaded) {
 		if(!data || (data.posts && !data.posts.length)) {
 			return;
diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl
index 36b3a63076..bd5b7e82b7 100644
--- a/public/templates/topic.tpl
+++ b/public/templates/topic.tpl
@@ -143,7 +143,7 @@
 			</li>
 
 			<!-- IF @first -->
-			<li class="well post-bar">
+			<li class="well post-bar" data-index="{posts.index}">
 				<div class="inline-block">
 					<small class="topic-stats">
 						<span>[[category:posts]]</span>
@@ -178,8 +178,8 @@
 		<!-- END posts -->
 	</ul>
 
-	<div class="well col-md-11 col-xs-12 pull-right hide">
-		<div class="topic-main-buttons pull-right inline-block hide">
+	<div class="well col-md-11 col-xs-12 pull-right post-bar bottom-post-bar hide">
+		<div class="topic-main-buttons pull-right inline-block">
 			<div class="loading-indicator" done="0" style="display:none;">
 				<span class="hidden-xs-inline">[[topic:loading_more_posts]]</span> <i class="fa fa-refresh fa-spin"></i>
 			</div>
diff --git a/src/categories.js b/src/categories.js
index d3d6f04c95..5131f8e57a 100644
--- a/src/categories.js
+++ b/src/categories.js
@@ -46,15 +46,14 @@ var db = require('./database.js'),
 		});
 	};
 
-	Categories.getCategoryById = function(category_id, current_user, callback) {
+	Categories.getCategoryById = function(category_id, start, end, current_user, callback) {
 		Categories.getCategoryData(category_id, function(err, categoryData) {
 			if (err) {
 				return callback(err);
 			}
 
 			function getTopicIds(next) {
-				var topicsPerPage = meta.config.topicsPerPage || 20;
-				Categories.getTopicIds(category_id, 0, topicsPerPage - 1, next);
+				Categories.getTopicIds(category_id, start, end, next);
 			}
 
 			function getActiveUsers(next) {
diff --git a/src/feed.js b/src/feed.js
index ac55c64460..89828328e1 100644
--- a/src/feed.js
+++ b/src/feed.js
@@ -84,7 +84,7 @@
 	};
 
 	Feed.updateCategory = function (cid, callback) {
-		categories.getCategoryById(cid, 0, function (err, categoryData) {
+		categories.getCategoryById(cid, 0, -1, 0, function (err, categoryData) {
 			if (err) return callback(new Error('category-invalid'));
 
 			var feed = new rss({
diff --git a/src/posts.js b/src/posts.js
index b4aa4c1882..b7048dc09c 100644
--- a/src/posts.js
+++ b/src/posts.js
@@ -468,4 +468,28 @@ var db = require('./database'),
 		});
 	}
 
+	Posts.getPidPage = function(pid, callback) {
+		Posts.getPostField(pid, 'tid', function(err, tid) {
+			if(err) {
+				return callback(err);
+			}
+
+			topics.getPids(tid, function(err, pids) {
+				if(err) {
+					return callback(err);
+				}
+
+				var index = pids.indexOf(pid);
+				if(index === -1) {
+					return callback(new Error('pid not found'));
+				}
+				var postsPerPage = parseInt(meta.config.postsPerPage, 10);
+				postsPerPage = postsPerPage ? postsPerPage : 20;
+
+				var page = Math.ceil((index + 1) / postsPerPage);
+				callback(null, page);
+			});
+		});
+	}
+
 }(exports));
diff --git a/src/routes/api.js b/src/routes/api.js
index 171dc5147d..f700334764 100644
--- a/src/routes/api.js
+++ b/src/routes/api.js
@@ -164,17 +164,33 @@ var path = require('path'),
 			});
 
 			app.get('/topic/:id/:slug?', function (req, res, next) {
-				console.log(req.query);
+
 				var uid = (req.user) ? req.user.uid : 0;
+				var page = 1;
+				if(req.query && req.query.page) {
+					page = req.query.page;
+				}
+
+				if(parseInt(page, 10) < 1) {
+					return res.send(404);
+				}
+
+				var postsPerPage = parseInt(meta.config.postsPerPage ? meta.config.postsPerPage : 20, 10);
+				var start = (page - 1) * postsPerPage;
+				var end = start + postsPerPage - 1;
 
 				ThreadTools.privileges(req.params.id, uid, function(err, privileges) {
 					if (privileges.read) {
-						var postsPerPage = parseInt(meta.config.postsPerPage ? meta.config.postsPerPage : 20, 10);
-						topics.getTopicWithPosts(req.params.id, uid, 0, postsPerPage - 1, false, function (err, data) {
+						topics.getTopicWithPosts(req.params.id, uid, start, end, false, function (err, data) {
 							if(err) {
 								return next(err);
 							}
-							data.currentPage = 1;
+
+							if(page > data.pageCount) {
+								return res.send(404);
+							}
+
+							data.currentPage = page;
 							data.privileges = privileges;
 
 							if (parseInt(data.deleted, 10) === 1 && parseInt(data.expose_tools, 10) === 0) {
@@ -191,16 +207,32 @@ var path = require('path'),
 
 			app.get('/category/:id/:slug?', function (req, res, next) {
 				var uid = (req.user) ? req.user.uid : 0;
+				var page = 1;
+				if(req.query && req.query.page) {
+					page = req.query.page;
+				}
+
+				if(parseInt(page, 10) < 1) {
+					return res.send(404);
+				}
+
+				var topicsPerPage = parseInt(meta.config.topicsPerPage ? meta.config.topicsPerPage : 20, 10);
+				var start = (page - 1) * topicsPerPage;
+				var end = start + topicsPerPage - 1;
 
 				// Category Whitelisting
 				categoryTools.privileges(req.params.id, uid, function(err, privileges) {
 					if (!err && privileges.read) {
-						categories.getCategoryById(req.params.id, uid, function (err, data) {
+						categories.getCategoryById(req.params.id, start, end, uid, function (err, data) {
 							if(err) {
 								return next(err);
 							}
 
-							data.currentPage = 1;
+							if(page > data.pageCount) {
+								return res.send(404);
+							}
+
+							data.currentPage = page;
 							data.privileges = privileges;
 
 							if (data && parseInt(data.disabled, 10) === 0) {
diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js
index ec663ee8e6..eaac85b4ac 100644
--- a/src/socket.io/categories.js
+++ b/src/socket.io/categories.js
@@ -28,23 +28,6 @@ SocketCategories.loadMore = function(socket, data, callback) {
 	});
 };
 
-SocketCategories.loadPage = function(socket, data, callback) {
-	if(!data) {
-		return callback(new Error('invalid data'));
-	}
-
-	var topicsPerPage = parseInt(meta.config.topicsPerPage, 10) || 20;
-
-	var start = (data.page - 1) * topicsPerPage,
-		end = start + topicsPerPage - 1;
-
-	categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, topics) {
-		callback(err, {
-			topics: topics
-		});
-	});
-}
-
 SocketCategories.getPageCount = function(socket, cid, callback) {
 	categories.getPageCount(cid, callback);
 }
diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js
index 652f09cada..14726ab0cb 100644
--- a/src/socket.io/posts.js
+++ b/src/socket.io/posts.js
@@ -194,4 +194,8 @@ SocketPosts.getFavouritedUsers = function(socket, pid, callback) {
 	});
 };
 
+SocketPosts.getPidPage = function(socket, pid, callback) {
+	posts.getPidPage(pid, callback);
+}
+
 module.exports = SocketPosts;
\ No newline at end of file
diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js
index 3a45f1293e..6ea39afbc9 100644
--- a/src/socket.io/topics.js
+++ b/src/socket.io/topics.js
@@ -245,31 +245,6 @@ SocketTopics.loadMore = function(socket, data, callback) {
 	});
 };
 
-SocketTopics.loadPage = function(socket, data, callback) {
-	if(!data || !data.tid || !data.page || parseInt(data.page < 0)) {
-		return callback(new Error('invalid data'));
-	}
-
-	var postsPerPage = parseInt((meta.config.postsPerPage ? meta.config.postsPerPage : 20), 10);
-
-	topics.getPageCount(data.tid, function(err, pageCount) {
-		if(err) {
-			return callback(err);
-		}
-
-		if(data.page > pageCount) {
-			return callback(new Error('page doesn\'t exist'));
-		}
-
-		var start = (data.page-1) * postsPerPage,
-			end = start + postsPerPage - 1;
-
-		topics.getTopicPosts(data.tid, start, end, socket.uid, function(err, posts) {
-			callback(err, {posts: posts});
-		});
-	});
-}
-
 SocketTopics.loadMoreRecentTopics = function(socket, data, callback) {
 	if(!data || !data.term) {
 		return callback(new Error('invalid data'));
diff --git a/src/webserver.js b/src/webserver.js
index ee5b1a0dc6..323a977522 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -9,6 +9,7 @@ var path = require('path'),
 	validator = require('validator'),
 	async = require('async'),
 	S = require('string'),
+	qs = require('querystring'),
 
 	pkg = require('../package.json'),
 
@@ -644,6 +645,10 @@ module.exports.server = server;
 				}
 
 				var topic_url = tid + (req.params.slug ? '/' + req.params.slug : '');
+				var queryString = qs.stringify(req.query);
+				if(queryString.length) {
+					topic_url += '?' + queryString;
+				}
 
 				res.send(
 					data.header +
@@ -701,7 +706,7 @@ module.exports.server = server;
 					});
 				},
 				function (next) {
-					categories.getCategoryById(cid, 0, function (err, categoryData) {
+					categories.getCategoryById(cid, 0, -1, 0, function (err, categoryData) {
 
 						if (categoryData) {
 							if (parseInt(categoryData.disabled, 10) === 1) {
@@ -758,6 +763,10 @@ module.exports.server = server;
 				}
 
 				var category_url = cid + (req.params.slug ? '/' + req.params.slug : '');
+				var queryString = qs.stringify(req.query);
+				if(queryString.length) {
+					category_url += '?' + queryString;
+				}
 
 				res.send(
 					data.header +
diff --git a/tests/categories.js b/tests/categories.js
index 6f83d774f8..ba9cf3b702 100644
--- a/tests/categories.js
+++ b/tests/categories.js
@@ -31,7 +31,7 @@ describe('Categories', function() {
 
 	describe('.getCategoryById', function() {
 		it('should retrieve a newly created category by its ID', function(done) {
-			Categories.getCategoryById(categoryObj.cid, 0, function(err, categoryData) {
+			Categories.getCategoryById(categoryObj.cid, 0, -1, 0, function(err, categoryData) {
 				assert(categoryData);
 				assert.equal(categoryObj.name, categoryData.category_name);
 				assert.equal(categoryObj.description, categoryData.category_description);