When using PHP's LDAP library, calling ldap_search() can produce the following error:
Warning: ldap_search(): Search: Size limit exceeded
ldap_error: Size limit exceeded (4)
Root cause: Active Directory limits LDAP queries to 1000 entries per page by default (MaxPageSize). If you need to retrieve more objects — e.g. all users in a larger AD — you have to implement paging.
The clean approach: use LDAP Paged Result Controls in PHP. Fetch results page by page, navigating through them via a cookie.
<?php
$ldap = ldap_connect("ldap://your-dc.domain.local");
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_bind($ldap, "cn=serviceuser,dc=domain,dc=local", "password");
$baseDn = "dc=domain,dc=local";
$filter = "(&(objectClass=user)(objectCategory=person))";
$pageSize = 500;
$cookie = "";
$allUsers = [];
do {
ldap_control_paged_result($ldap, $pageSize, true, $cookie);
$result = ldap_search($ldap, $baseDn, $filter, ["sAMAccountName", "mail", "displayName"]);
$entries = ldap_get_entries($ldap, $result);
for ($i = 0; $i < $entries["count"]; $i++) {
$allUsers[] = $entries[$i];
}
ldap_control_paged_result_response($ldap, $result, $cookie);
} while (!empty($cookie));
ldap_unbind($ldap);
echo "Users found: " . count($allUsers) . PHP_EOL;
?>
⚠️ PHP 8.0+: ldap_control_paged_result() is deprecated. Modern alternative using the $controls parameter:
$controls = [[
"oid" => LDAP_CONTROL_PAGEDRESULTS,
"iscritical" => false,
"value" => ["size" => 500, "cookie" => $cookie]
]];
$result = ldap_search($ldap, $baseDn, $filter, [], 0, 0, 0, LDAP_DEREF_NEVER, $controls);
ldap_parse_result($ldap, $result, $errcode, $matcheddn, $errmsg, $referrals, $retcontrols);
$cookie = $retcontrols[LDAP_CONTROL_PAGEDRESULTS]["value"]["cookie"] ?? "";
Alternatively, the AD-side limit can be raised via ntdsutil — but that's a global change to your AD configuration and usually the wrong approach.
👉 How-to: Adjusting MaxPageSize in Active Directory via ntdsutil
H@ppy H@cking! 🐘⚡