diff --git a/src/lxml/includes/etree_defs.h b/src/lxml/includes/etree_defs.h
index 81e3cbf0c230d0ec4ec23de6704d72738eb37115_c3JjL2x4bWwvaW5jbHVkZXMvZXRyZWVfZGVmcy5o..d3637936f6f49613231164d4cd6a20b2a90900b9_c3JjL2x4bWwvaW5jbHVkZXMvZXRyZWVfZGVmcy5o 100644
--- a/src/lxml/includes/etree_defs.h
+++ b/src/lxml/includes/etree_defs.h
@@ -36,5 +36,21 @@
 
 #ifdef PYPY_VERSION
 #    define IS_PYPY 1
+/*
+PyPy 4.0 contains some important cpyext fixes and identifies as Python 2.7.10 or 3.2.5,
+just like PyPy 2.6.1, which does not have these fixes.
+*/
+#    if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7 || \
+         PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7 && PY_MICRO_VERSION < 10 || \
+         PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 2 || \
+         PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 2 && PY_MICRO_VERSION < 5)
+     #define IS_PYPY26 1
+#    elif (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7 && PY_MICRO_VERSION == 10 || \
+           PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 2 && PY_MICRO_VERSION == 5)
+#    include "string.h"
+     #define IS_PYPY26  (strncmp(PYPY_VERSION, "2.", 2) == 0)
+#    else
+     #define IS_PYPY26 0
+#    endif
 #else
 #    define IS_PYPY 0
@@ -39,5 +55,6 @@
 #else
 #    define IS_PYPY 0
+#    define IS_PYPY26 0
 #endif
 
 #if PY_MAJOR_VERSION >= 3
diff --git a/src/lxml/proxy.pxi b/src/lxml/proxy.pxi
index 81e3cbf0c230d0ec4ec23de6704d72738eb37115_c3JjL2x4bWwvcHJveHkucHhp..d3637936f6f49613231164d4cd6a20b2a90900b9_c3JjL2x4bWwvcHJveHkucHhp 100644
--- a/src/lxml/proxy.pxi
+++ b/src/lxml/proxy.pxi
@@ -17,7 +17,7 @@
     """
     #print "getProxy for:", <int>c_node
     if c_node is not NULL and c_node._private is not NULL:
-        if python.IS_PYPY:
+        if python.IS_PYPY26:
             return <_Element>python.PyWeakref_LockObject(<python.PyObject*>c_node._private)
         else:
             return <_Element>c_node._private
@@ -29,9 +29,9 @@
 cdef inline bint hasProxy(xmlNode* c_node):
     if c_node._private is NULL:
         return False
-    if python.IS_PYPY:
-        return _isProxyAliveInPypy(c_node)
+    if python.IS_PYPY26:
+        return _isProxyAliveInPypy26(c_node)
     return True
 
 
 @cython.linetrace(False)
@@ -34,8 +34,8 @@
     return True
 
 
 @cython.linetrace(False)
-cdef bint _isProxyAliveInPypy(xmlNode* c_node):
+cdef bint _isProxyAliveInPypy26(xmlNode* c_node):
     retval = True
     if python.PyWeakref_LockObject(<python.PyObject*>c_node._private) is None:
         # proxy has already died => remove weak reference
@@ -55,7 +55,7 @@
     assert not hasProxy(c_node), u"double registering proxy!"
     proxy._doc = doc
     proxy._c_node = c_node
-    if python.IS_PYPY:
+    if python.IS_PYPY26:
         c_node._private = <void*>python.PyWeakref_NewRef(proxy, NULL)
     else:
         c_node._private = <void*>proxy
@@ -67,7 +67,7 @@
     u"""Unregister a proxy for the node it's proxying for.
     """
     cdef xmlNode* c_node = proxy._c_node
-    if python.IS_PYPY:
+    if python.IS_PYPY26:
         weakref_ptr = <python.PyObject*>c_node._private
         c_node._private = NULL
         python.Py_XDECREF(weakref_ptr)
diff --git a/src/lxml/python.pxd b/src/lxml/python.pxd
index 81e3cbf0c230d0ec4ec23de6704d72738eb37115_c3JjL2x4bWwvcHl0aG9uLnB4ZA==..d3637936f6f49613231164d4cd6a20b2a90900b9_c3JjL2x4bWwvcHl0aG9uLnB4ZA== 100644
--- a/src/lxml/python.pxd
+++ b/src/lxml/python.pxd
@@ -124,6 +124,7 @@
     cdef object PY_NEW(object t)
     cdef bint LXML_UNICODE_STRINGS
     cdef bint IS_PYTHON3
+    cdef bint IS_PYPY26
     cdef bint IS_PYPY
 
 cdef extern from "lxml_endian.h":