In Python, given x-value on 2D Bezier Curve, return y-value
The following script uses the formula for cubic Bezier curves (which Blender approximates) to first determine t (which is the parametrization of the curve) from x and then gets y from t.

import bpy
import numpy as np

def main():
    '''Here's an example usage of these functions'''    
    x = 5.0    
    bez_obj = bpy.data.objects['BezierCurve']

    print('The y-value is', getYfromXforBezierObject(bez_obj, x))



def getYfromXforBezierObject(bez_obj, x):
    '''Given a Bezier object which, when projected on to xy-plane, is a 
    well-behaved function (i.e. each x-value has only one associated y-value),
    this returns the y-value for a given x-value

    The higher resolution your curve is, the more accurate the resultant y-value
    will be.'''

    #find appropriate segment
    segment_i = determineBezSegment(bez_obj, x)

    if len(bez_obj.data.splines) &gt; 1:
        print("WARNING: your Bezier object has multiple splines!")

    spline = bez_obj.data.splines[0]

    #get the four points that control the cubic bezier segment
    P0 = spline.bezier_points[segment_i].co[:2]
    P1 = spline.bezier_points[segment_i].handle_right[:2]
    P2 = spline.bezier_points[segment_i+1].handle_left[:2]
    P3 = spline.bezier_points[segment_i+1].co[:2]  

    y = getYfromXforBezSegment(P0, P1, P2, P3, x)

    return y


def determineBezSegment(bez_obj, x):
    '''Given a Bezier object and an x-value, determine which of the cubic 
    segments corresponds to that x-value.
    A return value of 0 would represent the first segment.'''
    print(bez_obj.data)
    bez_points = bez_obj.data.splines[0].bezier_points

    if len(bez_obj.data.splines) &gt; 1:
        print("WARNING: your Bezier object has multiple splines!")

    #loop through all segments and find which one contains x
    for segment_i in range(len(bez_points)-1):
        start_point = bez_points[segment_i]
        end_point = bez_points[segment_i+1]
        #break if this segment contains x
        if start_point.co[0] &lt;= x &lt; end_point.co[0]:
            break
    #check if no segment was found
    else: 
        print("WARNING: no segment found for given x-value and Bezier object")
        return None

    return segment_i


def getYfromXforBezSegment(P0, P1, P2, P3, x):
    '''For a cubic Bezier segment described by the 2-tuples P0, ..., P3, return
    the y-value associated with the given x-value.

    Ex: getXfromYforCubicBez((0,0), (1,1), (2,1), (2,2), 3.2)'''

    #First, get the t-value associated with x-value, where t is the
    #parameterization of the Bezier curve and ranges from 0 to 1.
    #We need the coefficients of the polynomial describing cubic Bezier
    #(cubic polynomial in t)
    coefficients = [-P0[0] + 3*P1[0] - 3*P2[0] + P3[0],
                    3*P0[0] - 6*P1[0] + 3*P2[0],
                    -3*P0[0] + 3*P1[0],
                    P0[0] - x]
    #find roots of this polynomial to determine the parameter t
    roots = np.roots(coefficients)
    #find the root which is between 0 and 1, and is also real
    correct_root = None
    for root in roots:
        if np.isreal(root) and 0 &lt;= root &lt;= 1:
            correct_root = root

    #check to make sure a valid root was found
    if correct_root is None:
        print('Error, no valid root found. Are you sure your Bezier curve '
              'represents a valid function when projected into the xy-plane?')
    param_t = correct_root

    #from our value for the t parameter, find the corresponding y-value using formula for
    #cubic Bezier curves
    y = (1-param_t)**3*P0[1] + 3*(1-param_t)**2*param_t*P1[1] + 3*(1-param_t)*param_t**2*P2[1] + param_t**3*P3[1]
    assert np.isreal(y)
    # typecast y from np.complex128 to float64   
    y = y.real
    return y


if __name__ == '__main__':
    main()


This script will work only if your Bezier curve is a function when projected into the xy-plane (hit NUM7 and make sure it passes the "vertical line test").