Why not expand on this idea a bit, which requires JS to run and move the whole form to AJAX?
(If some *major* websites can require JS to register, why can't you?)
####### # ####### # #######
On the Registration Page:
####### # ####### # #######
<head>
<script type="text/javascript" src="http://www.example.com/register.js"></script>
</head>
<noscript>You MUST have JavaScript enabled to Register. Please adjust your browser settings and refresh this page. If you are unable to use JavaScript, please 'do something the tiny percentage of people who actually want to sign up and cannot run JS can do, but a bot can't, like make a phone call?' (Dunno, up to you.)</noscript>
<div id="ClickToRegister" onClick="showForm('LinkClicked');">Click Here to Register</div>
####### # ####### # #######
http://www.example.com/register.js is outlined below:
####### # ####### # #######
function showForm(realClick) {
/* Here's the key I see to making this *way* too much work for most people to bother with writing a bot for: Split the names of the input fields and JUMBLE the response between the php file and the .js file for the names of the input area. The 'real' field names I'm going to use are: VisitorName (= username), FromMailAddress (= email), KeyToLogin (= password) */
var inputField1="Address";
var inputField2="Name";
var inputField3="Key";
/* Make a POST request with "VarName=" + realClick; to 'getfieldnames.php' (or some other server-side script lang) here. */
/* http://www.example.com/getfieldnames.php checks to see if the POST variable matches VarName=LinkClicked, checks to ensure the POST actually came from your website, etc and if everything checks out, echo's "FormMail^ToLogin^Visitor"; */
var phpResult = http_request.responseText;
var fields=phpResult.split("^");
/* Remember:
inputField1="Address"; inputField2="Name"; inputField3="Key";
fields[0]="FormMail"; fields[1]="ToLogin"; fields[2]="Visitor"; */
var realInputField1 = fields[0]+inputField1;
var realInputField2 = fields[2]+inputField2;
var realInputField3 = inputField3+fields[1];
document.getElementById('ClickToRegister').innerHTML = "<form name=\"SignUp\" action=\"\" onSubmit=\"yourProcessingFunctionHere()\">" +
"<input type=\"text\" name=\"" + realInputField1 + "\" />" +
"<input type=\"text\" name=\"" + realInputField2 + "\" />" +
"<input type=\"password\" name=\"" + realInputField3 + "\" />" +
"<input type=\"submit\" name=\"submit\" />" +
"</form>";
}
####### # ####### # #######
Put a 2nd POST to PHP Function to Process the Form Below
####### # ####### # #######
function yourProcessingFunctionHere() {
/* Gather the values of the input fields and make a POST request to formvalidation.php, which passes the names and values of the fields in the form... */
/* If the names do not match, you will know someone either: */
/* A.) Tried to assemble your JavaScript and get the names for the form fields from there. */
/* B.) Found the php page, somehow made a post and tried to get the names of the form fields from there. */
/* C.) Just made something up, because the names I used are non-standard. */
/* The only way I can see to get the right names for the fields is to actually both parse the JS, and POST to the PHP, because to get the right names for the fields they have to put both together. (It means unless you've got a really advanced bot you probably can't automate signing up.) */
}
####### # ####### # #######
I wrote for basic readability and understandability, and of course this is a non-working, and definitely not a copy / paste example. I hope it gives you some ideas, because it's really tough to get past the methods of this one since you have to be able to both parse the JS, and POST to the PHP just to get the fields you need to submit the registration... You can also change any of it to 'unique to you' easily.
####### # ####### # #######