One time tested approach for me is to very precisely measure how long the fastest human could fill out a specific form in ms (must be done per form, and must consider browser autofilling). Then, include an encrypted timestamp value as a hidden field value on said form and check that:
1) The form was recently submitted (i.e. you cannot submit forms from two hours ago). Done well with another approach I take, this also catches bots that try to resubmit already cracked form instances. This is a bigger issue than you might give it credit for. Often they will crack a form instance by hand and then submit variations of fields they care to spam in programatically. Crack once by hand, submit spam 10000 times automatically therafter.
2) That the delta between receiving the form submission and when it was generated is greater than how long the fastest human would take.
It has a throttling effect to spamming (if nothing else), in addition to preventing most programatic spam. It is also nice that it does not depend on client-side javascript that can be tampered with. Used in combination with some other approaches, I have several sites that serve millions of users a year that all but remove the need for captchas (contact me if you are interested).