diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index e3235778a..8e97fa6cd 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -314,6 +314,7 @@ void content_mapnode_init()
 	f->solidness = 0;
 	f->air_equivalent = true;
 	f->walkable = false;
+	f->climbable = true;
 	setWoodLikeDiggingProperties(f->digging_properties, 0.5);
 
 	// Deprecated
diff --git a/src/mapnode.h b/src/mapnode.h
index 1fb84e1c9..484ad4e19 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -128,6 +128,8 @@ struct ContentFeatures
 	bool pointable;
 	// Player can dig these
 	bool diggable;
+        // Player can climb these
+        bool climbable;
 	// Player can build on these
 	bool buildable_to;
 	// Whether the node has no liquid, source liquid or flowing liquid
@@ -171,6 +173,7 @@ struct ContentFeatures
 		walkable = true;
 		pointable = true;
 		diggable = true;
+		climbable = false;
 		buildable_to = false;
 		liquid_type = LIQUID_NONE;
 		wall_mounted = false;
diff --git a/src/player.cpp b/src/player.cpp
index c43276ef1..3846cd8f9 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -375,6 +375,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
 		in_water_stable = false;
 	}
 
+	/*
+	        Check if player is climbing
+	*/
+
+	try {
+	        v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
+		v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
+		is_climbing = (content_features(map.getNode(pp).d).climbable ||
+			       content_features(map.getNode(pp2).d).climbable);
+	}
+	catch(InvalidPositionException &e)
+	{
+	        is_climbing = false;
+	}
+
 	/*
 		Collision uncertainty radius
 		Make it a bit larger than the maximum distance of movement
@@ -461,7 +476,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
 		Player is allowed to jump when this is true.
 	*/
 	touching_ground = false;
-	
+
 	/*std::cout<<"Checking collisions for ("
 			<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
 			<<") -> ("
@@ -814,6 +829,19 @@ void LocalPlayer::applyControl(float dtime)
 		}
 	}
 
+	if (is_climbing) {
+	        if (control.up || control.left || control.right || control.down) {
+		        v3f speed = getSpeed();
+			speed.Y = 2*BS;
+			setSpeed(speed);
+		}
+		else {
+		        v3f speed = getSpeed();
+			speed.Y = -2*BS;
+			setSpeed(speed);
+		}
+	}
+
 	// The speed of the player (Y is ignored)
 	if(superspeed)
 		speed = speed.normalize() * walkspeed_max * 5.0;
diff --git a/src/player.h b/src/player.h
index 29460e1e1..78ca14948 100644
--- a/src/player.h
+++ b/src/player.h
@@ -118,6 +118,7 @@ public:
 	bool in_water;
 	// This is more stable and defines the maximum speed of the player
 	bool in_water_stable;
+	bool is_climbing;
 	bool swimming_up;
 	
 	Inventory inventory;